From ed8ddcbd902db1ec39c230d6edeefec2a344dfa8 Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Mon, 16 Oct 2023 21:47:28 +0100 Subject: [PATCH 01/14] feature/cherrypick (#25) * Improved preconditions, adds Check and Require methods which are intended to throw different exception types under different circumstances. (#10) * Updated license text. (#11) * Update/general (#12) * General codebase updates. * Updated to .NET 7.0 and C# 11. Added Collection initializers * Added dictionary initializers that use tuples. * Removed unused imports. * Fixed failing test. * Updated github actions to compile .NET 7 * feature/comparable-hash (#13) * Added hash comparability for sorting. Updated editorconfig to respect final newline and updated files accordingly. * Added non-generic IComparable to Hash * Updated version to 6.0.0, and license text for next release. (#14) * feature/cryptography (#15) * Refactored `Empty` properties to readonly. * Added generic Merkle tree implementation. * Added tests for `ToDateTime`, `ToDateOnly` and `ToTimeOnly`. * Added `Salt` implementation. * Operator reordering and better documentation. * Global formatting changes. * Added features to MerkleTree implementation. * Added missing license text and salt tests. * Updated `ToDateTime` tests to UTC. * Removed unnecessary usings. * feature/units (#17) Added generic Temperature and DataSize units including tests. Added GenericMath functionality. Added TypeExtensions. * Major refactor to align implementations and provide better testing * Added `CountNot`, `None`, and `WhereNot` LINQ extensions. Also renamed `WhereIs` to `WhereInstanceOf`. (#20) * Added base specification pattern. * Added base repository and unit-of-work interfaces. (#22) * Added BigDecimal for .NET * Reverting additions: Data and Specifications. * Cherry-picked features for main --- .editorconfig | 1 + .github/workflows/dotnet.yml | 2 +- .../Objects}/Color.cs | 4 +- .../Objects/Element.cs | 31 ++ .../Objects/Numeric.cs | 47 ++ .../Objects/RecordLike.cs | 56 +++ .../OnixLabs.Core.UnitTests.Data.csproj | 28 ++ .../ArrayExtensionTests.cs | 65 +++ .../Collections/CollectionTests.cs | 418 ++++++++++++++++ OnixLabs.Core.UnitTests/EnumerationTests.cs | 70 ++- .../Linq/IEnumerableExtensionTests.cs | 447 ++++++++++++++++++ .../ObjectExtensionTests.cs | 36 ++ .../OnixLabs.Core.UnitTests.csproj | 15 +- OnixLabs.Core.UnitTests/PreconditionTests.cs | 22 +- .../Reflection/TypeExtensionTests.cs | 79 ++++ .../StringExtensionTests.cs | 155 ++++-- OnixLabs.Core.UnitTests/Text/Base16Tests.cs | 38 +- .../Text/Base32Base32HexAlphabetTests.cs | 50 +- .../Text/Base32CrockfordAlphabetTests.cs | 50 +- .../Text/Base32DefaultAlphabetTests.cs | 50 +- .../Text/Base32ZBase32AlphabetTests.cs | 50 +- .../Text/Base58DefaultAlphabetTests.cs | 38 +- .../Text/Base58FlickrAlphabetTests.cs | 38 +- .../Text/Base58RippleAlphabetTests.cs | 38 +- OnixLabs.Core.UnitTests/Text/Base64Tests.cs | 38 +- OnixLabs.Core/Collections/Collection.Empty.cs | 200 ++++++++ OnixLabs.Core/Collections/Collection.Of.cs | 267 +++++++++++ OnixLabs.Core/Enumeration.Comparable.cs | 8 +- OnixLabs.Core/Enumeration.Equatable.cs | 58 +-- OnixLabs.Core/Enumeration.From.cs | 11 +- OnixLabs.Core/Enumeration.Get.cs | 6 +- OnixLabs.Core/Enumeration.To.cs | 6 +- OnixLabs.Core/Enumeration.cs | 2 +- ...ArrayExtensions.cs => Extensions.Array.cs} | 17 +- OnixLabs.Core/Extensions.Object.cs | 59 +++ ...ringExtensions.cs => Extensions.String.cs} | 62 ++- OnixLabs.Core/HashCodeExtensions.cs | 53 --- OnixLabs.Core/Linq/Extensions.IEnumerable.cs | 246 ++++++++++ OnixLabs.Core/Linq/IEnumerableExtensions.cs | 178 ------- OnixLabs.Core/OnixLabs.Core.csproj | 23 +- OnixLabs.Core/Preconditions.cs | 55 ++- OnixLabs.Core/Reflection/Extensions.Type.cs | 61 +++ .../{Base16.Empty.cs => Base16.Constants.cs} | 16 +- OnixLabs.Core/Text/Base16.Create.cs | 54 +++ OnixLabs.Core/Text/Base16.Equatable.cs | 56 +-- OnixLabs.Core/Text/Base16.From.cs | 98 ---- OnixLabs.Core/Text/Base16.Parse.cs | 26 +- OnixLabs.Core/Text/Base16.To.cs | 4 +- OnixLabs.Core/Text/Base16.cs | 6 +- OnixLabs.Core/Text/Base32.Codec.cs | 6 +- .../{Base32.Empty.cs => Base32.Constants.cs} | 15 +- OnixLabs.Core/Text/Base32.Create.cs | 159 +++++++ OnixLabs.Core/Text/Base32.Equatable.cs | 56 +-- OnixLabs.Core/Text/Base32.From.cs | 349 -------------- OnixLabs.Core/Text/Base32.Parse.cs | 52 +- OnixLabs.Core/Text/Base32.To.cs | 2 +- OnixLabs.Core/Text/Base32.cs | 6 +- OnixLabs.Core/Text/Base32Alphabet.cs | 17 +- OnixLabs.Core/Text/Base58.Checksum.cs | 2 +- OnixLabs.Core/Text/Base58.Codec.cs | 4 +- .../{Base58.Empty.cs => Base58.Constants.cs} | 16 +- OnixLabs.Core/Text/Base58.Create.cs | 88 ++++ OnixLabs.Core/Text/Base58.Equatable.cs | 56 +-- OnixLabs.Core/Text/Base58.From.cs | 178 ------- OnixLabs.Core/Text/Base58.Parse.cs | 98 +--- OnixLabs.Core/Text/Base58.To.cs | 4 +- OnixLabs.Core/Text/Base58.cs | 6 +- OnixLabs.Core/Text/Base58Alphabet.cs | 11 +- .../{Base64.Empty.cs => Base64.Constants.cs} | 16 +- OnixLabs.Core/Text/Base64.Create.cs | 54 +++ OnixLabs.Core/Text/Base64.Equatable.cs | 56 +-- OnixLabs.Core/Text/Base64.From.cs | 98 ---- OnixLabs.Core/Text/Base64.Parse.cs | 28 +- OnixLabs.Core/Text/Base64.To.cs | 4 +- OnixLabs.Core/Text/Base64.cs | 6 +- OnixLabs.Core/Text/IBase.cs | 93 ++++ .../OnixLabs.Playground.csproj | 10 +- OnixLabs.Playground/Program.cs | 2 +- .../Objects/MerkleNode.cs | 63 +++ ...ecurity.Cryptography.UnitTests.Data.csproj | 32 ++ .../EcdsaEncryptedPkcs8Tests.cs | 2 +- .../EcdsaKeyPkcs8Tests.cs | 2 +- .../EcdsaKeyTests.cs | 10 +- .../HashAsyncTests.cs | 2 +- .../HashTests.cs | 48 +- .../HmacAsyncTests.cs | 2 +- .../HmacTests.cs | 2 +- .../KeyTestBase.cs | 2 +- .../MerkleTreeGenericTests.cs | 106 +++++ .../MerkleTreeTests.cs | 59 ++- ...abs.Security.Cryptography.UnitTests.csproj | 13 +- .../RsaKeyEncryptedPkcs8Tests.cs | 2 +- .../RsaKeyPkcs8Tests.cs | 2 +- .../RsaKeyTests.cs | 10 +- .../SaltTests.cs | 44 ++ .../Sha3Hash224Tests.cs | 2 +- .../Sha3Hash256Tests.cs | 2 +- .../Sha3Hash384Tests.cs | 2 +- .../Sha3Hash512Tests.cs | 2 +- .../Sha3HashTestBase.cs | 4 +- .../Sha3Shake128Tests.cs | 2 +- .../Sha3Shake256Tests.cs | 2 +- .../Sha3ShakeTestBase.cs | 4 +- ...Empty.cs => DigitalSignature.Constants.cs} | 14 +- ...ure.From.cs => DigitalSignature.Create.cs} | 20 +- .../DigitalSignature.Equatable.cs | 46 +- .../DigitalSignature.To.cs | 10 +- .../DigitalSignature.Validation.cs | 2 +- .../DigitalSignature.cs | 6 +- ...eKey.From.cs => EcdsaPrivateKey.Create.cs} | 23 +- .../EcdsaPrivateKey.Export.cs | 6 +- .../EcdsaPrivateKey.Get.cs | 4 +- .../EcdsaPrivateKey.Import.cs | 10 +- .../EcdsaPrivateKey.Sign.cs | 10 +- .../EcdsaPrivateKey.cs | 2 +- ...icKey.From.cs => EcdsaPublicKey.Create.cs} | 23 +- .../EcdsaPublicKey.Verify.cs | 6 +- .../EcdsaPublicKey.cs | 2 +- .../Hash.AllOneHash.cs | 8 +- .../Hash.AllZeroHash.cs | 8 +- .../Hash.Comparable.cs | 35 ++ .../Hash.Compute.Md5Hash.cs | 2 +- .../Hash.Compute.Sha1Hash.cs | 2 +- .../Hash.Compute.Sha2Hash256.cs | 2 +- .../Hash.Compute.Sha2Hash384.cs | 2 +- .../Hash.Compute.Sha2Hash512.cs | 2 +- .../Hash.Compute.Sha3Hash224.cs | 2 +- .../Hash.Compute.Sha3Hash256.cs | 2 +- .../Hash.Compute.Sha3Hash384.cs | 2 +- .../Hash.Compute.Sha3Hash512.cs | 2 +- .../Hash.Compute.Sha3Shake128.cs | 2 +- .../Hash.Compute.Sha3Shake256.cs | 2 +- .../Hash.Compute.cs | 6 +- .../Hash.ComputeAsync.Md5Hash.cs | 2 +- .../Hash.ComputeAsync.Sha1Hash.cs | 2 +- .../Hash.ComputeAsync.Sha2Hash256.cs | 2 +- .../Hash.ComputeAsync.Sha2Hash384.cs | 2 +- .../Hash.ComputeAsync.Sha2Hash512.cs | 2 +- .../Hash.ComputeAsync.Sha3Hash224.cs | 2 +- .../Hash.ComputeAsync.Sha3Hash256.cs | 2 +- .../Hash.ComputeAsync.Sha3Hash384.cs | 2 +- .../Hash.ComputeAsync.Sha3Hash512.cs | 2 +- .../Hash.ComputeAsync.Sha3Shake128.cs | 2 +- .../Hash.ComputeAsync.Sha3Shake256.cs | 2 +- .../Hash.ComputeAsync.cs | 6 +- .../Hash.ComputeTwice.cs | 6 +- .../Hash.ComputeTwiceAsync.cs | 6 +- .../Hash.Concantenate.cs | 15 +- .../{Hash.Empty.cs => Hash.Constants.cs} | 14 +- .../{Hash.From.cs => Hash.Create.cs} | 27 +- .../Hash.Equatable.cs | 46 +- OnixLabs.Security.Cryptography/Hash.Parse.cs | 8 +- OnixLabs.Security.Cryptography/Hash.To.cs | 10 +- OnixLabs.Security.Cryptography/Hash.cs | 7 +- .../HashAlgorithmType.Enumerations.cs | 2 +- .../HashAlgorithmType.Get.cs | 5 +- .../HashAlgorithmType.Verify.cs | 5 +- .../HashAlgorithmType.cs | 2 +- .../Hmac.Compute.Md5Hmac.cs | 3 +- .../Hmac.Compute.Sha1Hmac.cs | 3 +- .../Hmac.Compute.Sha2Hmac256.cs | 3 +- .../Hmac.Compute.Sha2Hmac384.cs | 3 +- .../Hmac.Compute.Sha2Hmac512.cs | 3 +- .../Hmac.Compute.cs | 7 +- .../Hmac.ComputeAsync.Md5Hmac.cs | 3 +- .../Hmac.ComputeAsync.Sha1Hmac.cs | 3 +- .../Hmac.ComputeAsync.Sha2Hmac256.cs | 3 +- .../Hmac.ComputeAsync.Sha2Hmac384.cs | 3 +- .../Hmac.ComputeAsync.Sha2Hmac512.cs | 3 +- .../Hmac.ComputeAsync.cs | 5 +- .../{Hmac.Empty.cs => Hmac.Constants.cs} | 14 +- OnixLabs.Security.Cryptography/Hmac.Create.cs | 6 +- .../Hmac.Equatable.cs | 46 +- OnixLabs.Security.Cryptography/Hmac.Parse.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.To.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Verify.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.cs | 4 +- OnixLabs.Security.Cryptography/IHashable.cs | 27 ++ .../KeyPair.Create.cs | 2 +- .../KeyPair.Equatable.cs | 46 +- .../KeyPair.From.cs | 7 +- OnixLabs.Security.Cryptography/KeyPair.cs | 2 +- .../MerkleTree.Build.cs | 103 ++++ .../MerkleTree.Equatable.cs | 46 +- .../MerkleTree.Generic.Build.cs | 83 ++++ .../MerkleTree.Generic.Equatable.cs | 71 +++ .../MerkleTree.Generic.Get.cs | 80 ++++ .../MerkleTree.Generic.cs | 99 ++++ .../MerkleTree.Get.cs | 51 ++ .../MerkleTree.To.cs | 27 ++ OnixLabs.Security.Cryptography/MerkleTree.cs | 138 +++--- .../MerkleTreeBranchNode.cs | 47 -- .../MerkleTreeLeafNode.cs | 54 --- .../OnixLabs.Security.Cryptography.csproj | 20 +- .../PrivateKey.Equatable.cs | 46 +- .../PrivateKey.Export.cs | 2 +- .../PrivateKey.Get.cs | 2 +- .../PrivateKey.Sign.cs | 2 +- .../PrivateKey.To.cs | 10 +- OnixLabs.Security.Cryptography/PrivateKey.cs | 7 +- .../PublicKey.Equatable.cs | 46 +- .../PublicKey.To.cs | 10 +- .../PublicKey.Verify.cs | 2 +- OnixLabs.Security.Cryptography/PublicKey.cs | 7 +- ...ateKey.From.cs => RsaPrivateKey.Create.cs} | 20 +- .../RsaPrivateKey.Equatable.cs | 2 +- .../RsaPrivateKey.Export.cs | 6 +- .../RsaPrivateKey.Get.cs | 2 +- .../RsaPrivateKey.Import.cs | 6 +- .../RsaPrivateKey.Sign.cs | 6 +- .../RsaPrivateKey.cs | 2 +- ...blicKey.From.cs => RsaPublicKey.Create.cs} | 20 +- .../RsaPublicKey.Equatable.cs | 2 +- .../RsaPublicKey.Verify.cs | 6 +- .../RsaPublicKey.cs | 2 +- OnixLabs.Security.Cryptography/Salt.Create.cs | 56 +++ .../Salt.Equatable.cs | 73 +++ OnixLabs.Security.Cryptography/Salt.To.cs | 60 +++ OnixLabs.Security.Cryptography/Salt.cs | 37 ++ OnixLabs.Security.Cryptography/Sha3.Create.cs | 2 +- .../Sha3.Permute.cs | 2 +- OnixLabs.Security.Cryptography/Sha3.cs | 8 +- OnixLabs.Security.Cryptography/Sha3Hash224.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Hash256.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Hash384.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Hash512.cs | 2 +- .../Sha3Shake128.cs | 2 +- .../Sha3Shake256.cs | 2 +- onixlabs-dotnet.sln | 17 + onixlabs-dotnet.sln.DotSettings | 70 +++ 230 files changed, 4933 insertions(+), 2428 deletions(-) rename {OnixLabs.Core.UnitTests/MockData => OnixLabs.Core.UnitTests.Data/Objects}/Color.cs (91%) create mode 100644 OnixLabs.Core.UnitTests.Data/Objects/Element.cs create mode 100644 OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs create mode 100644 OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs create mode 100644 OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj create mode 100644 OnixLabs.Core.UnitTests/ArrayExtensionTests.cs create mode 100644 OnixLabs.Core.UnitTests/Collections/CollectionTests.cs create mode 100644 OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs create mode 100644 OnixLabs.Core.UnitTests/ObjectExtensionTests.cs create mode 100644 OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs create mode 100644 OnixLabs.Core/Collections/Collection.Empty.cs create mode 100644 OnixLabs.Core/Collections/Collection.Of.cs rename OnixLabs.Core/{ArrayExtensions.cs => Extensions.Array.cs} (81%) create mode 100644 OnixLabs.Core/Extensions.Object.cs rename OnixLabs.Core/{StringExtensions.cs => Extensions.String.cs} (74%) delete mode 100644 OnixLabs.Core/HashCodeExtensions.cs create mode 100644 OnixLabs.Core/Linq/Extensions.IEnumerable.cs delete mode 100644 OnixLabs.Core/Linq/IEnumerableExtensions.cs create mode 100644 OnixLabs.Core/Reflection/Extensions.Type.cs rename OnixLabs.Core/Text/{Base16.Empty.cs => Base16.Constants.cs} (68%) create mode 100644 OnixLabs.Core/Text/Base16.Create.cs delete mode 100644 OnixLabs.Core/Text/Base16.From.cs rename OnixLabs.Core/Text/{Base32.Empty.cs => Base32.Constants.cs} (69%) create mode 100644 OnixLabs.Core/Text/Base32.Create.cs delete mode 100644 OnixLabs.Core/Text/Base32.From.cs rename OnixLabs.Core/Text/{Base58.Empty.cs => Base58.Constants.cs} (68%) create mode 100644 OnixLabs.Core/Text/Base58.Create.cs delete mode 100644 OnixLabs.Core/Text/Base58.From.cs rename OnixLabs.Core/Text/{Base64.Empty.cs => Base64.Constants.cs} (68%) create mode 100644 OnixLabs.Core/Text/Base64.Create.cs delete mode 100644 OnixLabs.Core/Text/Base64.From.cs create mode 100644 OnixLabs.Core/Text/IBase.cs create mode 100644 OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs create mode 100644 OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj create mode 100644 OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs create mode 100644 OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs rename OnixLabs.Security.Cryptography/{DigitalSignature.Empty.cs => DigitalSignature.Constants.cs} (70%) rename OnixLabs.Security.Cryptography/{DigitalSignature.From.cs => DigitalSignature.Create.cs} (84%) rename OnixLabs.Security.Cryptography/{EcdsaPrivateKey.From.cs => EcdsaPrivateKey.Create.cs} (82%) rename OnixLabs.Security.Cryptography/{EcdsaPublicKey.From.cs => EcdsaPublicKey.Create.cs} (82%) create mode 100644 OnixLabs.Security.Cryptography/Hash.Comparable.cs rename OnixLabs.Security.Cryptography/{Hash.Empty.cs => Hash.Constants.cs} (70%) rename OnixLabs.Security.Cryptography/{Hash.From.cs => Hash.Create.cs} (82%) rename OnixLabs.Security.Cryptography/{Hmac.Empty.cs => Hmac.Constants.cs} (72%) create mode 100644 OnixLabs.Security.Cryptography/IHashable.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Build.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Generic.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Get.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.To.cs delete mode 100644 OnixLabs.Security.Cryptography/MerkleTreeBranchNode.cs delete mode 100644 OnixLabs.Security.Cryptography/MerkleTreeLeafNode.cs rename OnixLabs.Security.Cryptography/{RsaPrivateKey.From.cs => RsaPrivateKey.Create.cs} (82%) rename OnixLabs.Security.Cryptography/{RsaPublicKey.From.cs => RsaPublicKey.Create.cs} (82%) create mode 100644 OnixLabs.Security.Cryptography/Salt.Create.cs create mode 100644 OnixLabs.Security.Cryptography/Salt.Equatable.cs create mode 100644 OnixLabs.Security.Cryptography/Salt.To.cs create mode 100644 OnixLabs.Security.Cryptography/Salt.cs create mode 100644 onixlabs-dotnet.sln.DotSettings diff --git a/.editorconfig b/.editorconfig index df8f9a8..a091931 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,3 +2,4 @@ root = true [*] max_line_length = 140 +insert_final_newline = true diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index fdee6ea..bbc4192 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -19,7 +19,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 6.0.x + dotnet-version: 7.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/OnixLabs.Core.UnitTests/MockData/Color.cs b/OnixLabs.Core.UnitTests.Data/Objects/Color.cs similarity index 91% rename from OnixLabs.Core.UnitTests/MockData/Color.cs rename to OnixLabs.Core.UnitTests.Data/Objects/Color.cs index 891e675..021ab6b 100644 --- a/OnixLabs.Core.UnitTests/MockData/Color.cs +++ b/OnixLabs.Core.UnitTests.Data/Objects/Color.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -namespace OnixLabs.Core.UnitTests.MockData; +namespace OnixLabs.Core.UnitTests.Data.Objects; public sealed class Color : Enumeration { diff --git a/OnixLabs.Core.UnitTests.Data/Objects/Element.cs b/OnixLabs.Core.UnitTests.Data/Objects/Element.cs new file mode 100644 index 0000000..38b3121 --- /dev/null +++ b/OnixLabs.Core.UnitTests.Data/Objects/Element.cs @@ -0,0 +1,31 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Core.UnitTests.Data.Objects; + +public sealed class Element +{ + public Element(int hashCode = 0) + { + HashCode = hashCode; + } + + public bool Called { get; set; } + private int HashCode { get; } + + public override int GetHashCode() + { + return HashCode; + } +} diff --git a/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs b/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs new file mode 100644 index 0000000..41300ce --- /dev/null +++ b/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs @@ -0,0 +1,47 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.UnitTests.Data.Objects; + +public sealed class Numeric : IEquatable> where T : INumber +{ + public Numeric(T value) + { + Value = value; + } + + public T Value { get; } + + public bool Equals(Numeric? other) + { + return other is not null && other.Value == Value; + } + + public override bool Equals(object? obj) + { + return obj is Numeric other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Value); + } + + public override string ToString() + { + return this.ToRecordString(); + } +} diff --git a/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs b/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs new file mode 100644 index 0000000..1fcfe81 --- /dev/null +++ b/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs @@ -0,0 +1,56 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Core.UnitTests.Data.Objects; + +public sealed class RecordLike : IEquatable +{ + public RecordLike(string text, int number, DateTime moment, Guid identifier) + { + Text = text; + Number = number; + Moment = moment; + Identifier = identifier; + } + + public string Text { get; } + public int Number { get; } + public DateTime Moment { get; } + public Guid Identifier { get; } + + public bool Equals(RecordLike? other) + { + return ReferenceEquals(this, other) + || other is not null + && other.Text == Text + && other.Number == Number + && other.Moment == Moment + && other.Identifier == Identifier; + } + + public override bool Equals(object? obj) + { + return Equals(obj as RecordLike); + } + + public override int GetHashCode() + { + return HashCode.Combine(Text, Number, Moment, Identifier); + } + + public override string ToString() + { + return $"RecordLike {{ Text = {Text}, Number = {Number}, Moment = {Moment}, Identifier = {Identifier} }}"; + } +} diff --git a/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj b/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj new file mode 100644 index 0000000..1182a5c --- /dev/null +++ b/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj @@ -0,0 +1,28 @@ + + + + net7.0 + enable + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs b/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs new file mode 100644 index 0000000..f2026e2 --- /dev/null +++ b/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs @@ -0,0 +1,65 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Core.UnitTests; + +public sealed class ArrayExtensionTests +{ + [Fact(DisplayName = "Array.Copy should produce a copy of an array")] + public void CopyShouldProduceExpectedResult() + { + // Given + int[] array = { 1, 2, 3, 4, 5 }; + int[] expected = { 1, 2, 3, 4, 5 }; + + // When + int[] actual = array.Copy(); + + // Then + Assert.Equal(expected, actual); + Assert.True(!ReferenceEquals(array, actual)); + } + + [Fact(DisplayName = "Array.Copy with index and count parameters should produce a copy of an array")] + public void CopyWithParametersShouldProduceExpectedResult() + { + // Given + int[] array = { 1, 2, 3, 4, 5 }; + int[] expected = { 3, 4, 5 }; + + // When + int[] actual = array.Copy(2, 3); + + // Then + Assert.Equal(expected, actual); + Assert.True(!ReferenceEquals(array, actual)); + } + + [Fact(DisplayName = "Array.ConcatenateWith should produce a concatenation of two arrays")] + public void ConcatenateWithShouldProduceExpectedResult() + { + // Given + int[] left = { 1, 2, 3, 4, 5 }; + int[] right = { 6, 7, 8, 9, 10 }; + int[] expected = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + + // When + int[] actual = left.ConcatenateWith(right); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs new file mode 100644 index 0000000..7d33dd7 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs @@ -0,0 +1,418 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using OnixLabs.Core.Collections; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Collections; + +public sealed class CollectionTests +{ + private static readonly object[] EnumerableInitializers = { true, false, 123, "abc", 1.23, true, false, 123, "abc", 1.23 }; + + private static readonly int[] NumericInitializers = { 123, 456, 789, 0, 1, -1, -987, 123, 456, 789, 0, 1, -1, -987 }; + + private static readonly KeyValuePair[] DictionaryInitializers = + { + new(123, true), + new("abc", null), + new(123.45f, "value") + }; + + private static readonly KeyValuePair[] SortedDictionaryInitializers = + { + new("key1", 123), + new("key2", false), + new("key3", "abc") + }; + + [Fact(DisplayName = "Collections.EmptyEnumerable should produce the expected result")] + public void CollectionsEmptyEnumerableShouldProduceTheExpectedResult() + { + // Given + IEnumerable expected = Enumerable.Empty(); + IEnumerable actual = Collection.EmptyEnumerable(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyArray should produce the expected result")] + public void CollectionsEmptyArrayShouldProduceTheExpectedResult() + { + // Given + object[] expected = Array.Empty(); + object[] actual = Collection.EmptyArray(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyImmutableArray should produce the expected result")] + public void CollectionsEmptyImmutableArrayShouldProduceTheExpectedResult() + { + // Given + ImmutableArray expected = ImmutableArray.Create(); + ImmutableArray actual = Collection.EmptyImmutableArray(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyList should produce the expected result")] + public void CollectionsEmptyListShouldProduceTheExpectedResult() + { + // Given + List expected = new(); + List actual = Collection.EmptyList(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyImmutableList should produce the expected result")] + public void CollectionsEmptyImmutableListShouldProduceTheExpectedResult() + { + // Given + ImmutableList expected = ImmutableList.Create(); + ImmutableList actual = Collection.EmptyImmutableList(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyDictionary should produce the expected result")] + public void CollectionsEmptyDictionaryShouldProduceTheExpectedResult() + { + // Given + Dictionary expected = new(); + Dictionary actual = Collection.EmptyDictionary(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyImmutableDictionary should produce the expected result")] + public void CollectionsEmptyImmutableDictionaryShouldProduceTheExpectedResult() + { + // Given + ImmutableDictionary expected = ImmutableDictionary.Create(); + ImmutableDictionary actual = Collection.EmptyImmutableDictionary(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptySortedDictionary should produce the expected result")] + public void CollectionsEmptySortedDictionaryShouldProduceTheExpectedResult() + { + // Given + SortedDictionary expected = new(); + SortedDictionary actual = Collection.EmptySortedDictionary(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyImmutableSortedDictionary should produce the expected result")] + public void CollectionsEmptyImmutableSortedDictionaryShouldProduceTheExpectedResult() + { + // Given + ImmutableSortedDictionary expected = ImmutableSortedDictionary.Create(); + ImmutableSortedDictionary actual = Collection.EmptyImmutableSortedDictionary(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyHashSet should produce the expected result")] + public void CollectionsEmptyHashSetShouldProduceTheExpectedResult() + { + // Given + HashSet expected = new(); + HashSet actual = Collection.EmptyHashSet(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyImmutableHashSet should produce the expected result")] + public void CollectionsEmptyImmutableHashSetShouldProduceTheExpectedResult() + { + // Given + ImmutableHashSet expected = ImmutableHashSet.Create(); + ImmutableHashSet actual = Collection.EmptyImmutableHashSet(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptySortedSet should produce the expected result")] + public void CollectionsEmptySortedSetShouldProduceTheExpectedResult() + { + // Given + SortedSet expected = new(); + SortedSet actual = Collection.EmptySortedSet(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyImmutableSortedSet should produce the expected result")] + public void CollectionsEmptyImmutableSortedSetShouldProduceTheExpectedResult() + { + // Given + ImmutableSortedSet expected = ImmutableSortedSet.Create(); + ImmutableSortedSet actual = Collection.EmptyImmutableSortedSet(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyStack should produce the expected result")] + public void CollectionsEmptyStackShouldProduceTheExpectedResult() + { + // Given + Stack expected = new(); + Stack actual = Collection.EmptyStack(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyImmutableStack should produce the expected result")] + public void CollectionsEmptyImmutableStackShouldProduceTheExpectedResult() + { + // Given + ImmutableStack expected = ImmutableStack.Create(); + ImmutableStack actual = Collection.EmptyImmutableStack(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyQueue should produce the expected result")] + public void CollectionsEmptyQueueShouldProduceTheExpectedResult() + { + // Given + Queue expected = new(); + Queue actual = Collection.EmptyQueue(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EmptyImmutableQueue should produce the expected result")] + public void CollectionsEmptyImmutableQueueShouldProduceTheExpectedResult() + { + // Given + ImmutableQueue expected = ImmutableQueue.Create(); + ImmutableQueue actual = Collection.EmptyImmutableQueue(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Collections.EnumerableOf should return the expected result")] + public void CollectionsEnumerableOfShouldReturnTheExpectedResult() + { + // Given + IEnumerable expected = EnumerableInitializers; + IEnumerable actual = Collection.EnumerableOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ArrayOf should return the expected result")] + public void CollectionsArrayOfShouldReturnTheExpectedResult() + { + // Given + object[] expected = EnumerableInitializers.ToArray(); + object[] actual = Collection.ArrayOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ImmutableArrayOf should return the expected result")] + public void CollectionsImmutableArrayOfShouldReturnTheExpectedResult() + { + // Given + ImmutableArray expected = ImmutableArray.Create(EnumerableInitializers); + ImmutableArray actual = Collection.ImmutableArrayOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ListOf should return the expected result")] + public void CollectionsListOfShouldReturnTheExpectedResult() + { + // Given + List expected = new(EnumerableInitializers); + List actual = Collection.ListOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ImmutableListOf should return the expected result")] + public void CollectionsImmutableListOfShouldReturnTheExpectedResult() + { + // Given + ImmutableList expected = ImmutableList.Create(EnumerableInitializers); + ImmutableList actual = Collection.ImmutableListOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.DictionaryOf should return the expected result")] + public void CollectionsDictionaryOfShouldReturnTheExpectedResult() + { + // Given + Dictionary expected = new(DictionaryInitializers); + Dictionary actual = Collection.DictionaryOf(DictionaryInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ImmutableDictionaryOf should return the expected result")] + public void CollectionsImmutableDictionaryOfShouldReturnTheExpectedResult() + { + // Given + ImmutableDictionary expected = new Dictionary(DictionaryInitializers).ToImmutableDictionary(); + ImmutableDictionary actual = Collection.ImmutableDictionaryOf(DictionaryInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.SortedDictionaryOf should return the expected result")] + public void CollectionsSortedDictionaryOfShouldReturnTheExpectedResult() + { + // Given + SortedDictionary expected = new(Collection.DictionaryOf(SortedDictionaryInitializers)); + SortedDictionary actual = Collection.SortedDictionaryOf(SortedDictionaryInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ImmutableSortedDictionaryOf should return the expected result")] + public void CollectionsImmutableSortedDictionaryOfShouldReturnTheExpectedResult() + { + // Given + SortedDictionary sorted = new(Collection.DictionaryOf(SortedDictionaryInitializers)); + ImmutableSortedDictionary expected = sorted.ToImmutableSortedDictionary(); + ImmutableSortedDictionary actual = Collection.ImmutableSortedDictionaryOf(SortedDictionaryInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.HashSetOf should return the expected result")] + public void CollectionsHashSetOfShouldReturnTheExpectedResult() + { + // Given + HashSet expected = new(EnumerableInitializers); + HashSet actual = Collection.HashSetOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ImmutableHashSetOf should return the expected result")] + public void CollectionsImmutableHashSetOfShouldReturnTheExpectedResult() + { + // Given + ImmutableHashSet expected = ImmutableHashSet.Create(EnumerableInitializers); + ImmutableHashSet actual = Collection.ImmutableHashSetOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.SortedSetOf should return the expected result")] + public void CollectionsSortedSetOfShouldReturnTheExpectedResult() + { + // Given + SortedSet expected = new(NumericInitializers); + SortedSet actual = Collection.SortedSetOf(NumericInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ImmutableSortedSetOf should return the expected result")] + public void CollectionsImmutableSortedSetOfShouldReturnTheExpectedResult() + { + // Given + ImmutableSortedSet expected = ImmutableSortedSet.Create(NumericInitializers); + ImmutableSortedSet actual = Collection.ImmutableSortedSetOf(NumericInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.StackOf should return the expected result")] + public void CollectionsStackOfShouldReturnTheExpectedResult() + { + // Given + Stack expected = new(EnumerableInitializers); + Stack actual = Collection.StackOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ImmutableStackOf should return the expected result")] + public void CollectionsImmutableStackOfShouldReturnTheExpectedResult() + { + // Given + ImmutableStack expected = ImmutableStack.Create(EnumerableInitializers); + ImmutableStack actual = Collection.ImmutableStackOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.QueueOf should return the expected result")] + public void CollectionsQueueOfShouldReturnTheExpectedResult() + { + // Given + Queue expected = new(EnumerableInitializers); + Queue actual = Collection.QueueOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } + + [Fact(DisplayName = "Collections.ImmutableQueueOf should return the expected result")] + public void CollectionsImmutableQueueOfShouldReturnTheExpectedResult() + { + // Given + ImmutableQueue expected = ImmutableQueue.Create(EnumerableInitializers); + ImmutableQueue actual = Collection.ImmutableQueueOf(EnumerableInitializers); + + // Then + Assert.True(expected.SequenceEqual(actual)); + } +} diff --git a/OnixLabs.Core.UnitTests/EnumerationTests.cs b/OnixLabs.Core.UnitTests/EnumerationTests.cs index 4d3dfd2..0799b72 100644 --- a/OnixLabs.Core.UnitTests/EnumerationTests.cs +++ b/OnixLabs.Core.UnitTests/EnumerationTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ // limitations under the License. using System.Collections.Generic; -using OnixLabs.Core.UnitTests.MockData; +using OnixLabs.Core.UnitTests.Data.Objects; using Xunit; namespace OnixLabs.Core.UnitTests; @@ -23,32 +23,32 @@ public sealed class EnumerationTests [Fact(DisplayName = "Enumerations should be equal")] public void EnumerationsShouldBeEqual() { - // Arrange + // Given Color a = Color.Red; Color b = Color.Red; - // Assert + // Then Assert.Equal(a, b); } [Fact(DisplayName = "Enumerations should not be equal")] public void EnumerationsShouldNotBeEqual() { - // Arrange + // Given Color a = Color.Red; Color b = Color.Blue; - // Assert + // Then Assert.NotEqual(a, b); } [Fact(DisplayName = "Enumeration should return all enumeration instances")] public void EnumerationsShouldReturnAllEnumerationInstances() { - // Arrange + // Given IEnumerable colors = Color.GetAll(); - // Assert + // Then Assert.Contains(colors, item => item == Color.Red); Assert.Contains(colors, item => item == Color.Green); Assert.Contains(colors, item => item == Color.Blue); @@ -57,30 +57,30 @@ public void EnumerationsShouldReturnAllEnumerationInstances() [Fact(DisplayName = "Enumeration.FromName should return the expected enumeration entry")] public void EnumerationFromNameShouldReturnTheExpectedEnumerationEntry() { - // Arrange + // Given Color color = Color.FromName("Green"); - // Assert + // Then Assert.Equal(Color.Green, color); } [Fact(DisplayName = "Enumeration.FromValue should return the expected enumeration entry")] public void EnumerationFromValueShouldReturnTheExpectedEnumerationEntry() { - // Arrange + // Given Color color = Color.FromValue(2); - // Assert + // Then Assert.Equal(Color.Green, color); } [Fact(DisplayName = "Enumeration.GetAll should return all enumeration entries")] public void EnumerationGetAllShouldReturnAllEnumerationEntries() { - // Arrange + // Given IEnumerable entries = Color.GetAll(); - // Assert + // Then Assert.Contains(Color.Blue, entries); Assert.Contains(Color.Green, entries); Assert.Contains(Color.Red, entries); @@ -89,10 +89,10 @@ public void EnumerationGetAllShouldReturnAllEnumerationEntries() [Fact(DisplayName = "Enumeration.GetEntries should return all enumeration entries")] public void EnumerationGetEntriesShouldReturnAllEnumerationEntries() { - // Arrange + // Given IEnumerable<(int Value, string Name)> entries = Color.GetEntries(); - // Assert + // Then Assert.Contains(Color.Blue.ToEntry(), entries); Assert.Contains(Color.Green.ToEntry(), entries); Assert.Contains(Color.Red.ToEntry(), entries); @@ -101,10 +101,10 @@ public void EnumerationGetEntriesShouldReturnAllEnumerationEntries() [Fact(DisplayName = "Enumeration.GetNames should return all enumeration names")] public void EnumerationGetNamesShouldReturnAllEnumerationNames() { - // Arrange + // Given IEnumerable entries = Color.GetNames(); - // Assert + // Then Assert.Contains(Color.Blue.Name, entries); Assert.Contains(Color.Green.Name, entries); Assert.Contains(Color.Red.Name, entries); @@ -113,12 +113,40 @@ public void EnumerationGetNamesShouldReturnAllEnumerationNames() [Fact(DisplayName = "Enumeration.GetValues should return all enumeration values")] public void EnumerationGetValuesShouldReturnAllEnumerationValues() { - // Arrange + // Given IEnumerable entries = Color.GetValues(); - // Assert + // Then Assert.Contains(Color.Blue.Value, entries); Assert.Contains(Color.Green.Value, entries); Assert.Contains(Color.Red.Value, entries); } -} \ No newline at end of file + + [Fact(DisplayName = "Enumeration.CompareTo as Enumeration should return the correct value")] + public void EnumerationCompareToAsEnumerationShouldReturnTheCorrectValue() + { + // Given + Color left = Color.Red; + Color right = Color.Blue; + + // When + int actual = left.CompareTo(right); + + // Then + Assert.Equal(-1, actual); + } + + [Fact(DisplayName = "Enumeration.CompareTo as Object should return the correct value")] + public void EnumerationCompareToAsObjectShouldReturnTheCorrectValue() + { + // Given + Color left = Color.Red; + object right = Color.Blue; + + // When + int actual = left.CompareTo(right); + + // Then + Assert.Equal(-1, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs new file mode 100644 index 0000000..466bdba --- /dev/null +++ b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs @@ -0,0 +1,447 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using OnixLabs.Core.Collections; +using OnixLabs.Core.Linq; +using OnixLabs.Core.UnitTests.Data.Objects; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Linq; + +// ReSharper disable InconsistentNaming +public sealed class IEnumerableExtensionTests +{ + [Fact(DisplayName = "IEnumerable.AllEqualBy should return true when all items are equal by the same property")] + public void AllEqualByShouldProduceExpectedResultTrue() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + + // When + bool result = elements.AllEqualBy(element => element.Text); + + // Then + Assert.True(result); + } + + [Fact(DisplayName = "IEnumerable.AllEqualBy should return false when all items are not equal by the same property")] + public void AllEqualByShouldProduceExpectedResultFalse() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("xyz", 123, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + + // When + bool result = elements.AllEqualBy(element => element.Text); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.AnyEqualBy should return true when any items are equal by the same property")] + public void AnyEqualByShouldProduceExpectedResultTrue() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("xyz", 123, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + + // When + bool result = elements.AnyEqualBy(element => element.Text); + + // Then + Assert.True(result); + } + + [Fact(DisplayName = "IEnumerable.AnyEqualBy should return false when any items are not equal by the same property")] + public void AnyEqualByShouldProduceExpectedResultFalse() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("def", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("xyz", 123, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + + // When + bool result = elements.AnyEqualBy(element => element.Text); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.CountNot should produce the expected result.")] + public void CountNotShouldProduceExpectedResult() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("def", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("xyz", 456, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + const int expected = 2; + + // When + int actual = elements.CountNot(element => element.Number == 456); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.ForEach should iterate over every element in the enumerable")] + public void ForEachShouldProduceExpectedResult() + { + // Given + IEnumerable enumerable = new[] { new Element(), new Element(), new Element() }; + + // When + enumerable.ForEach(element => element.Called = true); + + // Then + Assert.All(enumerable, element => Assert.True(element.Called)); + } + + [Fact(DisplayName = "IEnumerable.GetContentHashCode should produce equal hash codes")] + public void GetContentHashCodeShouldProduceExpectedResultEqual() + { + // Given + IEnumerable enumerable1 = new[] { new Element(1), new Element(2), new Element(3) }; + IEnumerable enumerable2 = new[] { new Element(1), new Element(2), new Element(3) }; + + // When + int hashCode1 = enumerable1.GetContentHashCode(); + int hashCode2 = enumerable2.GetContentHashCode(); + + // Then + Assert.Equal(hashCode1, hashCode2); + } + + [Fact(DisplayName = "IEnumerable.GetContentHashCode should produce different hash codes")] + public void GetContentHashCodeShouldProduceExpectedResultDifferent() + { + // Given + IEnumerable enumerable1 = new[] { new Element(1), new Element(2), new Element(3) }; + IEnumerable enumerable2 = new[] { new Element(3), new Element(2), new Element(1) }; + + // When + int hashCode1 = enumerable1.GetContentHashCode(); + int hashCode2 = enumerable2.GetContentHashCode(); + + // Then + Assert.NotEqual(hashCode1, hashCode2); + } + + [Fact(DisplayName = "IEnumerable.IsEmpty should return true when the enumerable is empty")] + public void IsEmptyShouldProduceExpectedResultTrue() + { + // Given + IEnumerable enumerable = Enumerable.Empty(); + + // When + bool result = enumerable.IsEmpty(); + + // Then + Assert.True(result); + } + + [Fact(DisplayName = "IEnumerable.IsEmpty should return false when the enumerable is not empty")] + public void IsEmptyShouldProduceExpectedResultFalse() + { + // Given + IEnumerable enumerable = new[] { new Element() }; + + // When + bool result = enumerable.IsEmpty(); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.IsNotEmpty should return true when the enumerable is not empty")] + public void IsNotEmptyShouldProduceExpectedResultTrue() + { + // Given + IEnumerable enumerable = new[] { new Element() }; + + // When + bool result = enumerable.IsNotEmpty(); + + // Then + Assert.True(result); + } + + [Fact(DisplayName = "IEnumerable.IsNotEmpty should return false when the enumerable is empty")] + public void IsNotEmptyShouldProduceExpectedResultFalse() + { + // Given + IEnumerable enumerable = Enumerable.Empty(); + + // When + bool result = enumerable.IsNotEmpty(); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.IsSingle should return true when the enumerable contains a single element")] + public void IsSingleShouldProduceExpectedResultTrue() + { + // Given + IEnumerable enumerable = new[] { new Element() }; + + // When + bool result = enumerable.IsSingle(); + + // Then + Assert.True(result); + } + + [Fact(DisplayName = "IEnumerable.IsSingle should return false when the enumerable is empty")] + public void IsSingleShouldProduceExpectedResultFalseWhenEmpty() + { + // Given + IEnumerable enumerable = Enumerable.Empty(); + + // When + bool result = enumerable.IsSingle(); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.IsSingle should return false when the enumerable contains more than one element")] + public void IsSingleShouldProduceExpectedResultFalseWhenMoreThanOneElement() + { + // Given + IEnumerable enumerable = new[] { new Element(), new Element() }; + + // When + bool result = enumerable.IsSingle(); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.IsCountEven should return true when the enumerable contains an even number of elements")] + public void IsCountEvenShouldProduceExpectedResultTrue() + { + // Given + IEnumerable enumerable = new[] { new Element(), new Element() }; + + // When + bool result = enumerable.IsCountEven(); + + // Then + Assert.True(result); + } + + [Fact(DisplayName = "IEnumerable.IsCountEven should return false when the enumerable contains an odd number of elements")] + public void IsCountEvenShouldProduceExpectedResultFalse() + { + // Given + IEnumerable enumerable = new[] { new Element() }; + + // When + bool result = enumerable.IsCountEven(); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.IsCountOdd should return true when the enumerable contains an odd number of elements")] + public void IsCountOddShouldProduceExpectedResultTrue() + { + // Given + IEnumerable enumerable = new[] { new Element() }; + + // When + bool result = enumerable.IsCountOdd(); + + // Then + Assert.True(result); + } + + [Fact(DisplayName = "IEnumerable.IsCountOdd should return false when the enumerable contains an even number of elements")] + public void IsCountOddShouldProduceExpectedResultFalse() + { + // Given + IEnumerable enumerable = new[] { new Element(), new Element() }; + + // When + bool result = enumerable.IsCountOdd(); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.JoinToString should produce the expected result with the default separator")] + public void JoinToStringShouldProduceExpectedResultWithDefaultSeparator() + { + // Given + IEnumerable enumerable = new object[] { 1, 2, 3, 4.5, true, false }; + const string expected = "1, 2, 3, 4.5, True, False"; + + // When + string actual = enumerable.JoinToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.JoinToString should produce the expected result with a custom separator")] + public void JoinToStringShouldProduceExpectedResultWithCustomSeparator() + { + // Given + IEnumerable enumerable = new object[] { 1, 2, 3, 4.5, true, false }; + const string expected = "1 *$ 2 *$ 3 *$ 4.5 *$ True *$ False"; + + // When + string actual = enumerable.JoinToString(" *$ "); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.None should return true when none of the elements satisfy the specified predicate condition")] + public void NoneShouldProduceExpectedResultTrue() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("def", 456, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("xyz", 789, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + + // When + bool result = elements.None(element => element.Number == 0); + + // Then + Assert.True(result); + } + + [Fact(DisplayName = "IEnumerable.None should return false when any of the elements satisfy the specified predicate condition")] + public void NoneShouldProduceExpectedResultFalseAny() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("def", 456, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("xyz", 0, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + + // When + bool result = elements.None(element => element.Number == 0); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.None should return false when all of the elements satisfy the specified predicate condition")] + public void NoneShouldProduceExpectedResultFalseAll() + { + // Given + RecordLike element1 = new("abc", 0, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("def", 0, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("xyz", 0, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + + // When + bool result = elements.None(element => element.Number == 0); + + // Then + Assert.False(result); + } + + [Fact(DisplayName = "IEnumerable.Sum should produce the expected result")] + public void SumShouldProduceExpectedResult() + { + // Given + IEnumerable elements = Collection.ListOf(12.34m, 34.56m, 56.78m); + decimal expected = 103.68m; + + // When + decimal actual = elements.Sum(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.Sum with selector should produce the expected result")] + public void SumWithSelectorShouldProduceExpectedResult() + { + // Given + Numeric element1 = new(1234.567m); + Numeric element2 = new(890.1234m); + Numeric element3 = new(56.78901m); + IEnumerable> elements = Collection.ListOf(element1, element2, element3); + decimal expected = 2181.47941m; + + // When + decimal actual = elements.SumBy(element => element.Value); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.WhereInstanceOf should return the correct elements matching the specified type")] + public void WhereInstanceOfShouldProduceExpectedResult() + { + // Given + IEnumerable enumerable = new object[] { 1, 2, 3, 4.5, true, false, Guid.NewGuid() }; + + // When + IEnumerable numbers = enumerable.WhereInstanceOf(); + + // Then + Assert.True(numbers.Count() == 3); + } + + [Fact(DisplayName = "IEnumerable.WhereNot should produce the expected result")] + public void WhereNotShouldProduceExpectedResult() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("def", 456, DateTime.Now, Guid.NewGuid()); + RecordLike element3 = new("xyz", 789, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, element3 }; + IEnumerable expected = new[] { element2, element3 }; + + // When + IEnumerable actual = elements.WhereNot(element => element.Number == 123); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.WhereNotNull should produce the expected result")] + public void WhereNotNullShouldProduceExpectedResult() + { + // Given + RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); + RecordLike element2 = new("def", 456, DateTime.Now, Guid.NewGuid()); + IEnumerable elements = new[] { element1, element2, null }; + IEnumerable expected = new[] { element1, element2 }; + + // When + IEnumerable actual = elements.WhereNotNull(); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs b/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs new file mode 100644 index 0000000..c5583a1 --- /dev/null +++ b/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs @@ -0,0 +1,36 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using OnixLabs.Core.UnitTests.Data.Objects; +using Xunit; + +namespace OnixLabs.Core.UnitTests; + +public sealed class ObjectExtensionTests +{ + [Fact(DisplayName = "Object.ToRecordString should produce a record formatted string")] + public void ToRecordStringShouldProduceExpectedResult() + { + // Given + RecordLike record = new("abc", 123, DateTime.Now, Guid.NewGuid()); + string expected = record.ToString(); + + // When + string actual = record.ToRecordString(); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj index 0ec43ac..957c6ca 100644 --- a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj +++ b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj @@ -1,17 +1,17 @@ - net6.0 + net7.0 false - 10 + 11 - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -22,7 +22,12 @@ + + + + + diff --git a/OnixLabs.Core.UnitTests/PreconditionTests.cs b/OnixLabs.Core.UnitTests/PreconditionTests.cs index 8331dc2..f5ff49d 100644 --- a/OnixLabs.Core.UnitTests/PreconditionTests.cs +++ b/OnixLabs.Core.UnitTests/PreconditionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,14 +21,26 @@ namespace OnixLabs.Core.UnitTests; public sealed class PreconditionTests { [Fact(DisplayName = "Check should throw an ArgumentException when the condition is false")] - public void CheckShouldThrowAnArgumentExceptionWhenTheConditionIsFalse() + public void CheckShouldProduceExpectedResult() { - Assert.Throws(() => Check(false)); + Assert.Throws(() => Check(false)); } [Fact(DisplayName = "CheckNotNull should throw an ArgumentNullException when the condition is null")] - public void CheckNotNullShouldThrowAnArgumentNullExceptionWhenTheConditionIsNull() + public void CheckNotNullShouldProduceExpectedResult() { - Assert.Throws(() => CheckNotNull(null)); + Assert.Throws(() => CheckNotNull(null)); + } + + [Fact(DisplayName = "Require should throw an ArgumentException when the condition is false")] + public void RequireShouldProduceExpectedResult() + { + Assert.Throws(() => Require(false)); + } + + [Fact(DisplayName = "RequireNotNull should throw an ArgumentNullException when the condition is null")] + public void RequireNotNullShouldProduceExpectedResult() + { + Assert.Throws(() => RequireNotNull(null)); } } diff --git a/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs b/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs new file mode 100644 index 0000000..012d861 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs @@ -0,0 +1,79 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using OnixLabs.Core.Reflection; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Reflection; + +public sealed class TypeExtensionTests +{ + [Fact(DisplayName = "Type.GetSimpleName from non-generic type should produce the expected type name")] + public void GetSimpleNameShouldProduceExpectedResultFromNonGenericType() + { + // Given + Type type = typeof(object); + const string expected = "Object"; + + // When + string actual = type.GetSimpleName(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Type.GetSimpleName from generic type should produce the expected type name")] + public void GetSimpleNameShouldProduceExpectedResultFromGenericType() + { + // Given + Type type = typeof(Dictionary>); + const string expected = "Dictionary"; + + // When + string actual = type.GetSimpleName(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Type.GetFormattedName from non-generic type should produce the expected type name")] + public void GetFormattedNameShouldProduceExpectedResultFromNonGenericType() + { + // Given + Type type = typeof(object); + const string expected = "Object"; + + // When + string actual = type.GetFormattedName(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Type.GetFormattedName from generic type should produce the expected type name")] + public void GetFormattedNameShouldProduceExpectedResultFromGenericType() + { + // Given + Type type = typeof(Dictionary>); + const string expected = "Dictionary>"; + + // When + string actual = type.GetFormattedName(); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/StringExtensionTests.cs b/OnixLabs.Core.UnitTests/StringExtensionTests.cs index 2908b43..5e0057c 100644 --- a/OnixLabs.Core.UnitTests/StringExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/StringExtensionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,128 +12,191 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.Globalization; using Xunit; namespace OnixLabs.Core.UnitTests; public sealed class StringExtensionTests { - [Theory(DisplayName = "SubstringBefore should return the expected result (char)")] + [Theory(DisplayName = "String.Repeat should return the expected result")] + [InlineData("0", 10, "0000000000")] + [InlineData("Abc1", 3, "Abc1Abc1Abc1")] + public void RepeatShouldProduceExpectedResult(string value, int count, string expected) + { + // When + string actual = value.Repeat(count); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "String.SubstringBeforeFirst should return the string before the first delimiter")] [InlineData("First:Second", "First", ':')] [InlineData("12345+678910", "12345", '+')] - public void SubstringBeforeShouldReturnTheExpectedResultChar(string value, string expected, char delimiter) + public void SubstringBeforeFirstShouldProduceExpectedResultChar(string value, string expected, char delimiter) { - // Arrange / Act - string actual = value.SubstringBefore(delimiter); + // When + string actual = value.SubstringBeforeFirst(delimiter); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "SubstringBefore should return the expected result (string)")] + [Theory(DisplayName = "String.SubstringBeforeFirst should return the string before the first delimiter")] [InlineData("First:Second", "First", ":")] [InlineData("12345+678910", "12345", "+")] - public void SubstringBeforeShouldReturnTheExpectedResultString(string value, string expected, string delimiter) + public void SubstringBeforeFirstShouldProduceExpectedResultString(string value, string expected, string delimiter) { - // Arrange / Act - string actual = value.SubstringBefore(delimiter); + // When + string actual = value.SubstringBeforeFirst(delimiter); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "SubstringBeforeLast should return the expected result (char)")] + [Theory(DisplayName = "String.SubstringBeforeLast should return the string before the last char delimiter")] [InlineData("First:Second:Third", "First:Second", ':')] [InlineData("12345+678910+12345", "12345+678910", '+')] - public void SubstringBeforeLastShouldReturnTheExpectedResultChar(string value, string expected, char delimiter) + public void SubstringBeforeLastShouldProduceExpectedResultChar(string value, string expected, char delimiter) { - // Arrange / Act + // When string actual = value.SubstringBeforeLast(delimiter); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "SubstringBeforeLast should return the expected result (string)")] + [Theory(DisplayName = "String.SubstringBeforeLast should return the string before the last string delimiter")] [InlineData("First:Second:Third", "First:Second", ":")] [InlineData("12345+678910+12345", "12345+678910", "+")] - public void SubstringBeforeLastShouldReturnTheExpectedResultString(string value, string expected, string delimiter) + public void SubstringBeforeLastShouldProduceExpectedResultString(string value, string expected, string delimiter) { - // Arrange / Act + // When string actual = value.SubstringBeforeLast(delimiter); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "SubstringAfter should return the expected result (char)")] + [Theory(DisplayName = "String.SubstringAfterFirst should return the string after the first char delimiter")] [InlineData("First:Second", "Second", ':')] [InlineData("12345+678910", "678910", '+')] - public void SubstringAfterShouldReturnTheExpectedResultChar(string value, string expected, char delimiter) + public void SubstringAfterFirstShouldProduceExpectedResultChar(string value, string expected, char delimiter) { - // Arrange / Act - string actual = value.SubstringAfter(delimiter); + // When + string actual = value.SubstringAfterFirst(delimiter); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "SubstringAfter should return the expected result (string)")] + [Theory(DisplayName = "String.SubstringAfterFirst should return the string after the first string delimiter")] [InlineData("First:Second", "Second", ":")] [InlineData("12345+678910", "678910", "+")] - public void SubstringAfterShouldReturnTheExpectedResultString(string value, string expected, string delimiter) + public void SubstringAfterFirstShouldProduceExpectedResultString(string value, string expected, string delimiter) { - // Arrange / Act - string actual = value.SubstringAfter(delimiter); + // When + string actual = value.SubstringAfterFirst(delimiter); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "SubstringAfterLast should return the expected result (char)")] + [Theory(DisplayName = "String.SubstringAfterLast should return the string after the last char delimiter")] [InlineData("First:Second:Third", "Third", ':')] [InlineData("12345+678910+12345", "12345", '+')] - public void SubstringAfterLastShouldReturnTheExpectedResultChar(string value, string expected, char delimiter) + public void SubstringAfterLastShouldProduceExpectedResultChar(string value, string expected, char delimiter) { - // Arrange / Act + // When string actual = value.SubstringAfterLast(delimiter); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "SubstringAfterLast should return the expected result (string)")] + [Theory(DisplayName = "String.SubstringAfterLast should return the the string after the last string delimiter")] [InlineData("First:Second:Third", "Third", ":")] [InlineData("12345+678910+12345", "12345", "+")] - public void SubstringAfterLastShouldReturnTheExpectedResultString(string value, string expected, string delimiter) + public void SubstringAfterLastShouldProduceExpectedResultString(string value, string expected, string delimiter) { - // Arrange / Act + // When string actual = value.SubstringAfterLast(delimiter); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "ToByteArray should return the expected result")] - [InlineData("Hello, World!", new byte[] {0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21})] - public void ToByteArrayShouldReturnTheExpectedResult(string value, byte[] expected) + [Theory(DisplayName = "String.ToByteArray should produce the byte array equivalent of the current string")] + [InlineData("Hello, World!", new byte[] { 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21 })] + public void ToByteArrayShouldProduceExpectedResult(string value, byte[] expected) { - // Arrange / Act + // When byte[] actual = value.ToByteArray(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Wrap should return the expected result")] + [Theory(DisplayName = "String.ToDateTime should return the DateTime equivalent of the current string")] + [InlineData("0001-01-01T00:00:00Z", 1, 1, 1, 0, 0, 0)] + [InlineData("1970-01-01T00:00:00Z", 1970, 1, 1, 0, 0, 0)] + [InlineData("9999-12-31T23:59:59Z", 9999, 12, 31, 23, 59, 59)] + public void ToDateTimeShouldProduceExpectedResult(string value, int year, int month, int day, int hour, int minute, int second) + { + // When + // AdjustToUniversal is essential, otherwise the tests may pass locally but fail on a build server in another time-zone. + DateTime actual = value.ToDateTime(styles: DateTimeStyles.AdjustToUniversal); + + // Then + Assert.Equal(year, actual.Year); + Assert.Equal(month, actual.Month); + Assert.Equal(day, actual.Day); + Assert.Equal(hour, actual.Hour); + Assert.Equal(minute, actual.Minute); + Assert.Equal(second, actual.Second); + } + + [Theory(DisplayName = "String.ToDateOnly should return the DateOnly equivalent of the current string")] + [InlineData("0001-01-01", 1, 1, 1)] + [InlineData("1970-01-01", 1970, 1, 1)] + [InlineData("9999-12-31", 9999, 12, 31)] + public void ToDateOnlyShouldProduceExpectedResult(string value, int year, int month, int day) + { + // When + DateOnly actual = value.ToDateOnly(); + + // Then + Assert.Equal(year, actual.Year); + Assert.Equal(month, actual.Month); + Assert.Equal(day, actual.Day); + } + + [Theory(DisplayName = "String.ToTimeOnly should return the TimeOnly equivalent of the current string")] + [InlineData("00:00:00", 0, 0, 0)] + [InlineData("01:01:01", 1, 1, 1)] + [InlineData("23:59:59", 23, 59, 59)] + public void ToTimeOnlyShouldProduceExpectedResult(string value, int hour, int minute, int second) + { + // When + TimeOnly actual = value.ToTimeOnly(); + + // Then + Assert.Equal(hour, actual.Hour); + Assert.Equal(minute, actual.Minute); + Assert.Equal(second, actual.Second); + } + + [Theory(DisplayName = "String.Wrap should wrap the current string value between the before and after string values")] [InlineData("<", "value", ">", "")] [InlineData("BEFORE:", "value", ":AFTER", "BEFORE:value:AFTER")] - public void WrapShouldReturnTheExpectedResult(string before, string value, string after, string expected) + public void WrapShouldProduceExpectedResult(string before, string value, string after, string expected) { - // Arrange / Act + // When string actual = value.Wrap(before, after); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base16Tests.cs b/OnixLabs.Core.UnitTests/Text/Base16Tests.cs index 2d5cc56..1e973bd 100644 --- a/OnixLabs.Core.UnitTests/Text/Base16Tests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base16Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,50 +19,50 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base16Tests { - [Fact(DisplayName = "Identical Base16 values produce identical hash codes.")] - public void IdenticalBase16ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base16 values should be identical")] + public void Base16ValuesShouldBeIdentical() { - // Arrange - Base16 a = Base16.FromString("abcdefghijklmnopqrstuvwxyz"); - Base16 b = Base16.FromString("abcdefghijklmnopqrstuvwxyz"); + // Given + Base16 a = Base16.Create("abcdefghijklmnopqrstuvwxyz"); + Base16 b = Base16.Create("abcdefghijklmnopqrstuvwxyz"); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base16_FromString should produce the expected Base-16 value.")] + [Theory(DisplayName = "Base16.Create should produce the expected Base-16 value")] [InlineData("31323334353637383930", "1234567890")] [InlineData("4142434445464748494a4b4c4d4e4f505152535455565758595a", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("6162636465666768696a6b6c6d6e6f707172737475767778797a", "abcdefghijklmnopqrstuvwxyz")] - public void Base16FromStringShouldProduceTheExpectedBase16Value(string expected, string value) + public void CreateShouldProduceExpectedResult(string expected, string value) { - // Arrange - Base16 candidate = Base16.FromString(value); + // Given + Base16 candidate = Base16.Create(value); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base16_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base16.Parse should produce the expected plain text value")] [InlineData("1234567890", "31323334353637383930")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "4142434445464748494a4b4c4d4e4f505152535455565758595a")] [InlineData("abcdefghijklmnopqrstuvwxyz", "6162636465666768696a6b6c6d6e6f707172737475767778797a")] - public void Base16ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base16 candidate = Base16.Parse(value); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs index 0754051..ce5bc0b 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,66 +19,66 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base32Base32HexAlphabetTests { - [Fact(DisplayName = "Identical Base32 values produce identical hash codes.")] - public void IdenticalBase32ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base32 values should be identical")] + public void Base32ValuesShouldBeIdentical() { - // Arrange - Base32 a = Base32.FromString("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Base32Hex); - Base32 b = Base32.FromString("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Base32Hex); + // Given + Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Base32Hex); + Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Base32Hex); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base32_FromString without padding should produce the expected Base-32 value.")] + [Theory(DisplayName = "Base32.Create with padding should produce the expected Base-32 value")] [InlineData("64P36D1L6ORJGE9G", "1234567890")] [InlineData("85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8======", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8======", "abcdefghijklmnopqrstuvwxyz")] - public void Base32FromStringWithPaddingShouldProduceTheExpectedBase32Value(string expected, string value) + public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) { - // Arrange - Base32 candidate = Base32.FromString(value, Base32Alphabet.Base32Hex, true); + // Given + Base32 candidate = Base32.Create(value, Base32Alphabet.Base32Hex, true); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base32_FromString without padding should produce the expected Base-32 value.")] + [Theory(DisplayName = "Base32.Create without padding should produce the expected Base-32 value")] [InlineData("64P36D1L6ORJGE9G", "1234567890")] [InlineData("85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8", "abcdefghijklmnopqrstuvwxyz")] - public void Base32FromStringWithoutPaddingShouldProduceTheExpectedBase32Value(string expected, string value) + public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) { - // Arrange - Base32 candidate = Base32.FromString(value, Base32Alphabet.Base32Hex, false); + // Given + Base32 candidate = Base32.Create(value, Base32Alphabet.Base32Hex, false); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base32_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base32.Parse should produce the expected plain text value")] [InlineData("1234567890", "64P36D1L6ORJGE9G")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8")] [InlineData("abcdefghijklmnopqrstuvwxyz", "C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8")] - public void Base32ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base32 candidate = Base32.Parse(value, Base32Alphabet.Base32Hex); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs index ad3c782..b63345b 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,66 +19,66 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base32CrockfordAlphabetTests { - [Fact(DisplayName = "Identical Base32 values produce identical hash codes.")] - public void IdenticalBase32ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base32 values should be identical")] + public void Base32ValuesShouldBeIdentical() { - // Arrange - Base32 a = Base32.FromString("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Crockford); - Base32 b = Base32.FromString("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Crockford); + // Given + Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Crockford); + Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Crockford); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base32_FromString without padding should produce the expected Base-32 value.")] + [Theory(DisplayName = "Base32.Create with padding should produce the expected Base-32 value")] [InlineData("64S36D1N6RVKGE9G", "1234567890")] [InlineData("85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8======", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8======", "abcdefghijklmnopqrstuvwxyz")] - public void Base32FromStringWithPaddingShouldProduceTheExpectedBase32Value(string expected, string value) + public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) { - // Arrange - Base32 candidate = Base32.FromString(value, Base32Alphabet.Crockford, true); + // Given + Base32 candidate = Base32.Create(value, Base32Alphabet.Crockford, true); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base32_FromString without padding should produce the expected Base-32 value.")] + [Theory(DisplayName = "Base32.Create without padding should produce the expected Base-32 value")] [InlineData("64S36D1N6RVKGE9G", "1234567890")] [InlineData("85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8", "abcdefghijklmnopqrstuvwxyz")] - public void Base32FromStringWithoutPaddingShouldProduceTheExpectedBase32Value(string expected, string value) + public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) { - // Arrange - Base32 candidate = Base32.FromString(value, Base32Alphabet.Crockford, false); + // Given + Base32 candidate = Base32.Create(value, Base32Alphabet.Crockford, false); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base32_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base32.Parse should produce the expected plain text value")] [InlineData("1234567890", "64S36D1N6RVKGE9G")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8")] [InlineData("abcdefghijklmnopqrstuvwxyz", "C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8")] - public void Base32ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base32 candidate = Base32.Parse(value, Base32Alphabet.Crockford); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs index 64be871..b976013 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,66 +19,66 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base32DefaultAlphabetTests { - [Fact(DisplayName = "Identical Base32 values produce identical hash codes.")] - public void IdenticalBase32ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base32 values should be identical")] + public void Base32ValuesShouldBeIdentical() { - // Arrange - Base32 a = Base32.FromString("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Default); - Base32 b = Base32.FromString("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Default); + // Given + Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Default); + Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Default); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base32_FromString without padding should produce the expected Base-32 value.")] + [Theory(DisplayName = "Base32.Create with padding should produce the expected Base-32 value")] [InlineData("GEZDGNBVGY3TQOJQ", "1234567890")] [InlineData("IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI======", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI======", "abcdefghijklmnopqrstuvwxyz")] - public void Base32FromStringWithPaddingShouldProduceTheExpectedBase32Value(string expected, string value) + public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) { - // Arrange - Base32 candidate = Base32.FromString(value, Base32Alphabet.Default, true); + // Given + Base32 candidate = Base32.Create(value, Base32Alphabet.Default, true); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base32_FromString without padding should produce the expected Base-32 value.")] + [Theory(DisplayName = "Base32.Create without padding should produce the expected Base-32 value")] [InlineData("GEZDGNBVGY3TQOJQ", "1234567890")] [InlineData("IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI", "abcdefghijklmnopqrstuvwxyz")] - public void Base32FromStringWithoutPaddingShouldProduceTheExpectedBase32Value(string expected, string value) + public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) { - // Arrange - Base32 candidate = Base32.FromString(value, Base32Alphabet.Default, false); + // Given + Base32 candidate = Base32.Create(value, Base32Alphabet.Default, false); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base32_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base32.Parse should produce the expected plain text value")] [InlineData("1234567890", "GEZDGNBVGY3TQOJQ")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI")] [InlineData("abcdefghijklmnopqrstuvwxyz", "MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI")] - public void Base32ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base32 candidate = Base32.Parse(value, Base32Alphabet.Default); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs index 9fcf4a5..9efc9da 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,66 +19,66 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base32ZBase32AlphabetTests { - [Fact(DisplayName = "Identical Base32 values produce identical hash codes.")] - public void IdenticalBase32ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base32 values should be identical")] + public void Base32ValuesShouldBeIdentical() { - // Arrange - Base32 a = Base32.FromString("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.ZBase32); - Base32 b = Base32.FromString("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.ZBase32); + // Given + Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.ZBase32); + Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.ZBase32); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base32_FromString without padding should produce the expected Base-32 value.")] + [Theory(DisplayName = "Base32.Create with padding should produce the expected Base-32 value")] [InlineData("gr3dgpbiga5uoqjo", "1234567890")] [InlineData("efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me======", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe======", "abcdefghijklmnopqrstuvwxyz")] - public void Base32FromStringWithPaddingShouldProduceTheExpectedBase32Value(string expected, string value) + public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) { - // Arrange - Base32 candidate = Base32.FromString(value, Base32Alphabet.ZBase32, true); + // Given + Base32 candidate = Base32.Create(value, Base32Alphabet.ZBase32, true); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base32_FromString without padding should produce the expected Base-32 value.")] + [Theory(DisplayName = "Base32.Create without padding should produce the expected Base-32 value")] [InlineData("gr3dgpbiga5uoqjo", "1234567890")] [InlineData("efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe", "abcdefghijklmnopqrstuvwxyz")] - public void Base32FromStringWithoutPaddingShouldProduceTheExpectedBase32Value(string expected, string value) + public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) { - // Arrange - Base32 candidate = Base32.FromString(value, Base32Alphabet.ZBase32, false); + // Given + Base32 candidate = Base32.Create(value, Base32Alphabet.ZBase32, false); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base32_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base32.Parse should produce the expected plain text value")] [InlineData("1234567890", "gr3dgpbiga5uoqjo")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me")] [InlineData("abcdefghijklmnopqrstuvwxyz", "cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe")] - public void Base32ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base32 candidate = Base32.Parse(value, Base32Alphabet.ZBase32); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs index f59cb61..5436846 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,50 +19,50 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base58DefaultAlphabetTests { - [Fact(DisplayName = "Identical Base58 values produce identical hash codes.")] - public void IdenticalBase58ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base58 values should be identical")] + public void Base58ValuesShouldBeIdentical() { - // Arrange - Base58 a = Base58.FromString("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Default); - Base58 b = Base58.FromString("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Default); + // Given + Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Default); + Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Default); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base58_FromString should produce the expected Base-58 value.")] + [Theory(DisplayName = "Base58.Create should produce the expected Base-58 value")] [InlineData("3mJr7AoUCHxNqd", "1234567890")] [InlineData("2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f", "abcdefghijklmnopqrstuvwxyz")] - public void Base58FromStringShouldProduceTheExpectedBase58Value(string expected, string value) + public void CreateShouldProduceExpectedResult(string expected, string value) { - // Arrange - Base58 candidate = Base58.FromString(value, Base58Alphabet.Default); + // Given + Base58 candidate = Base58.Create(value, Base58Alphabet.Default); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base58_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base58.Parse should produce the expected plain text value")] [InlineData("1234567890", "3mJr7AoUCHxNqd")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD")] [InlineData("abcdefghijklmnopqrstuvwxyz", "3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f")] - public void Base58ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base58 candidate = Base58.Parse(value, Base58Alphabet.Default); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs index 64cc7e2..a2c649c 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,50 +19,50 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base58FlickrAlphabetTests { - [Fact(DisplayName = "Identical Base58 values produce identical hash codes.")] - public void IdenticalBase58ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base58 values should be identical")] + public void Base58ValuesShouldBeIdentical() { - // Arrange - Base58 a = Base58.FromString("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Flickr); - Base58 b = Base58.FromString("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Flickr); + // Given + Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Flickr); + Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Flickr); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base58_FromString should produce the expected Base-58 value.")] + [Theory(DisplayName = "Base58.Create should produce the expected Base-58 value")] [InlineData("3LiR7aNtchXnQC", "1234567890")] [InlineData("2ZUfwsirsqj6erKTQGm2pdbKcMh1t46cMXzd", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("3YXt3U1HFx8vKFTJj92EAipcC4byHHs1V25E", "abcdefghijklmnopqrstuvwxyz")] - public void Base58FromStringShouldProduceTheExpectedBase58Value(string expected, string value) + public void CreateShouldProduceExpectedResult(string expected, string value) { - // Arrange - Base58 candidate = Base58.FromString(value, Base58Alphabet.Flickr); + // Given + Base58 candidate = Base58.Create(value, Base58Alphabet.Flickr); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base58_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base58.Parse should produce the expected plain text value")] [InlineData("1234567890", "3LiR7aNtchXnQC")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "2ZUfwsirsqj6erKTQGm2pdbKcMh1t46cMXzd")] [InlineData("abcdefghijklmnopqrstuvwxyz", "3YXt3U1HFx8vKFTJj92EAipcC4byHHs1V25E")] - public void Base58ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base58 candidate = Base58.Parse(value, Base58Alphabet.Flickr); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs index 381776c..a0fa2d6 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,50 +19,50 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base58RippleAlphabetTests { - [Fact(DisplayName = "Identical Base58 values produce identical hash codes.")] - public void IdenticalBase58ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base58 values should be identical")] + public void Base58ValuesShouldBeIdentical() { - // Arrange - Base58 a = Base58.FromString("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Ripple); - Base58 b = Base58.FromString("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Ripple); + // Given + Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Ripple); + Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Ripple); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base58_FromString should produce the expected Base-58 value.")] + [Theory(DisplayName = "Base58.Create should produce the expected Base-58 value")] [InlineData("smJifwo7UHx4qd", "1234567890")] [InlineData("pzuEXTJSTRKaNSktq6MpQDBkU8Hr7haU8x2D", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("syx7sur5gY3WkgtjK9pCbJQUdhBZ55TrvpnC", "abcdefghijklmnopqrstuvwxyz")] - public void Base58FromStringShouldProduceTheExpectedBase58Value(string expected, string value) + public void CreateShouldProduceExpectedResult(string expected, string value) { - // Arrange - Base58 candidate = Base58.FromString(value, Base58Alphabet.Ripple); + // Given + Base58 candidate = Base58.Create(value, Base58Alphabet.Ripple); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base58_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base58.Parse should produce the expected plain text value")] [InlineData("1234567890", "smJifwo7UHx4qd")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "pzuEXTJSTRKaNSktq6MpQDBkU8Hr7haU8x2D")] [InlineData("abcdefghijklmnopqrstuvwxyz", "syx7sur5gY3WkgtjK9pCbJQUdhBZ55TrvpnC")] - public void Base58ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base58 candidate = Base58.Parse(value, Base58Alphabet.Ripple); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core.UnitTests/Text/Base64Tests.cs b/OnixLabs.Core.UnitTests/Text/Base64Tests.cs index d9da9b7..e75114c 100644 --- a/OnixLabs.Core.UnitTests/Text/Base64Tests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base64Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,50 +19,50 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base64Tests { - [Fact(DisplayName = "Identical Base64 values produce identical hash codes.")] - public void IdenticalBase64ValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Base64 values should be identical")] + public void Base64ValuesShouldBeIdentical() { - // Arrange - Base64 a = Base64.FromString("abcdefghijklmnopqrstuvwxyz"); - Base64 b = Base64.FromString("abcdefghijklmnopqrstuvwxyz"); + // Given + Base64 a = Base64.Create("abcdefghijklmnopqrstuvwxyz"); + Base64 b = Base64.Create("abcdefghijklmnopqrstuvwxyz"); - // Act + // When int hashCodeA = a.GetHashCode(); int hashCodeB = b.GetHashCode(); - // Assert + // Then Assert.Equal(hashCodeA, hashCodeB); } - [Theory(DisplayName = "Base64_FromString should produce the expected Base-64 value.")] + [Theory(DisplayName = "Base64.Create should produce the expected Base-64 value")] [InlineData("MTIzNDU2Nzg5MA==", "1234567890")] [InlineData("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", "abcdefghijklmnopqrstuvwxyz")] - public void Base64FromStringShouldProduceTheExpectedBase64Value(string expected, string value) + public void CreateShouldProduceExpectedResult(string expected, string value) { - // Arrange - Base64 candidate = Base64.FromString(value); + // Given + Base64 candidate = Base64.Create(value); - // Act + // When string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base64_Parse should produce the expected plain text value.")] + [Theory(DisplayName = "Base64.Parse should produce the expected plain text value")] [InlineData("1234567890", "MTIzNDU2Nzg5MA==")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=")] [InlineData("abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=")] - public void Base64ParseShouldProduceTheExpectedPlainTextValue(string expected, string value) + public void ParseShouldProduceExpectedResult(string expected, string value) { - // Arrange + // Given Base64 candidate = Base64.Parse(value); - // Act + // When string actual = candidate.ToPlainTextString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Core/Collections/Collection.Empty.cs b/OnixLabs.Core/Collections/Collection.Empty.cs new file mode 100644 index 0000000..7c1fede --- /dev/null +++ b/OnixLabs.Core/Collections/Collection.Empty.cs @@ -0,0 +1,200 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace OnixLabs.Core.Collections; + +/// +/// Provides methods to create empty or populated mutable and immutable collections. +/// +public static partial class Collection +{ + /// + /// Creates an empty enumerable. + /// + /// The underlying type of the enumerable. + /// Returns an empty enumerable. + public static IEnumerable EmptyEnumerable() + { + return Enumerable.Empty(); + } + + /// + /// Creates an empty array. + /// + /// The underlying type of the array. + /// Returns an empty array. + public static T[] EmptyArray() + { + return Array.Empty(); + } + + /// + /// Creates an empty immutable array. + /// + /// The underlying type of the immutable array. + /// Returns an empty immutable array. + public static ImmutableArray EmptyImmutableArray() + { + return EmptyArray().ToImmutableArray(); + } + + /// + /// Creates an empty list. + /// + /// The underlying type of the list. + /// Returns an empty list. + public static List EmptyList() + { + return new List(); + } + + /// + /// Creates an empty immutable list. + /// + /// The underlying type of the immutable list. + /// Returns an empty immutable list. + public static ImmutableList EmptyImmutableList() + { + return EmptyList().ToImmutableList(); + } + + /// + /// Creates an empty dictionary. + /// + /// The underlying type of the dictionary key. + /// The underlying type of the dictionary value. + /// Returns an empty dictionary. + public static Dictionary EmptyDictionary() where TKey : notnull + { + return new Dictionary(); + } + + /// + /// Creates an empty immutable dictionary. + /// + /// The underlying type of the immutable dictionary key. + /// The underlying type of the immutable dictionary value. + /// Returns an empty immutable dictionary. + public static ImmutableDictionary EmptyImmutableDictionary() where TKey : notnull + { + return EmptyDictionary().ToImmutableDictionary(); + } + + /// + /// Creates an empty sorted dictionary. + /// + /// The underlying type of the sorted dictionary key. + /// The underlying type of the sorted dictionary value. + /// Returns an empty sorted dictionary. + public static SortedDictionary EmptySortedDictionary() where TKey : notnull + { + return new SortedDictionary(); + } + + /// + /// Creates an empty immutable sorted dictionary. + /// + /// The underlying type of the immutable sorted dictionary key. + /// The underlying type of the immutable sorted dictionary value. + /// Returns an empty immutable sorted dictionary. + public static ImmutableSortedDictionary EmptyImmutableSortedDictionary() where TKey : notnull + { + return EmptySortedDictionary().ToImmutableSortedDictionary(); + } + + /// + /// Creates an empty hash set. + /// + /// The underlying type of the hash set. + /// Returns an empty hash set. + public static HashSet EmptyHashSet() + { + return new HashSet(); + } + + /// + /// Creates an empty immutable hash set. + /// + /// The underlying type of the immutable hash set. + /// Returns an empty immutable hash set. + public static ImmutableHashSet EmptyImmutableHashSet() + { + return EmptyHashSet().ToImmutableHashSet(); + } + + /// + /// Creates an empty sorted set. + /// + /// The underlying type of the sorted set. + /// Returns an empty sorted set. + public static SortedSet EmptySortedSet() + { + return new SortedSet(); + } + + /// + /// Creates an empty immutable sorted set. + /// + /// The underlying type of the immutable sorted set. + /// Returns an empty immutable sorted set. + public static ImmutableSortedSet EmptyImmutableSortedSet() + { + return EmptySortedSet().ToImmutableSortedSet(); + } + + /// + /// Creates an empty stack. + /// + /// The underlying type of the stack. + /// Returns an empty stack. + public static Stack EmptyStack() + { + return new Stack(); + } + + /// + /// Creates an empty immutable stack. + /// + /// The underlying type of the immutable stack. + /// Returns an empty immutable stack. + public static ImmutableStack EmptyImmutableStack() + { + return ImmutableStack.Create(); + } + + /// + /// Creates an empty queue. + /// + /// The underlying type of the queue. + /// Returns an empty queue. + public static Queue EmptyQueue() + { + return new Queue(); + } + + /// + /// Creates an empty immutable queue. + /// + /// The underlying type of the immutable queue. + /// Returns an empty immutable queue. + public static ImmutableQueue EmptyImmutableQueue() + { + return ImmutableQueue.Create(); + } +} diff --git a/OnixLabs.Core/Collections/Collection.Of.cs b/OnixLabs.Core/Collections/Collection.Of.cs new file mode 100644 index 0000000..cde7d88 --- /dev/null +++ b/OnixLabs.Core/Collections/Collection.Of.cs @@ -0,0 +1,267 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace OnixLabs.Core.Collections; + +public static partial class Collection +{ + /// + /// Creates an enumerable of the specified items. + /// + /// The items which will populate the enumerable. + /// The underlying type of the enumerable. + /// Returns an enumerable populated with the specified items. + public static IEnumerable EnumerableOf(params T[] items) + { + return items.Copy(); + } + + /// + /// Creates an array of the specified items. + /// + /// The items which will populate the array. + /// The underlying type of the array. + /// Returns an array populated with the specified items. + public static T[] ArrayOf(params T[] items) + { + return items.Copy(); + } + + /// + /// Creates an immutable array of the specified items. + /// + /// The items which will populate the immutable array. + /// The underlying type of the immutable array. + /// Returns an immutable array populated with the specified items. + public static ImmutableArray ImmutableArrayOf(params T[] items) + { + return ArrayOf(items).ToImmutableArray(); + } + + /// + /// Creates a list of the specified items. + /// + /// The items which will populate the list. + /// The underlying type of the list. + /// Returns a list populated with the specified items. + public static List ListOf(params T[] items) + { + return new List(items.Copy()); + } + + /// + /// Creates an immutable list of the specified items. + /// + /// The items which will populate the immutable list. + /// The underlying type of the immutable list. + /// Returns an immutable list populated with the specified items. + public static ImmutableList ImmutableListOf(params T[] items) + { + return ListOf(items).ToImmutableList(); + } + + /// + /// Create a dictionary of the specified items. + /// + /// The items which wil populate the dictionary. + /// The underlying type of the dictionary key. + /// The underlying type of the dictionary value. + /// Returns a dictionary populated with the specified items. + public static Dictionary DictionaryOf(params KeyValuePair[] items) where TKey : notnull + { + return new Dictionary(items.Copy()); + } + + /// + /// Create a dictionary of the specified items. + /// + /// The items which wil populate the dictionary. + /// The underlying type of the dictionary key. + /// The underlying type of the dictionary value. + /// Returns a dictionary populated with the specified items. + public static Dictionary DictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull + { + return DictionaryOf(items.Select(item => new KeyValuePair(item.key, item.value)).ToArray()); + } + + /// + /// Create an immutable dictionary of the specified items. + /// + /// The items which wil populate the immutable dictionary. + /// The underlying type of the immutable dictionary key. + /// The underlying type of the immutable dictionary value. + /// Returns an immutable dictionary populated with the specified items. + public static ImmutableDictionary ImmutableDictionaryOf( + params KeyValuePair[] items) where TKey : notnull + { + return DictionaryOf(items).ToImmutableDictionary(); + } + + /// + /// Create an immutable dictionary of the specified items. + /// + /// The items which wil populate the immutable dictionary. + /// The underlying type of the immutable dictionary key. + /// The underlying type of the immutable dictionary value. + /// Returns an immutable dictionary populated with the specified items. + public static ImmutableDictionary ImmutableDictionaryOf( + params (TKey key, TValue value)[] items) where TKey : notnull + { + return DictionaryOf(items).ToImmutableDictionary(); + } + + /// + /// Create a sorted dictionary of the specified items. + /// + /// The items which wil populate the sorted dictionary. + /// The underlying type of the sorted dictionary key. + /// The underlying type of the sorted dictionary value. + /// Returns a sorted dictionary populated with the specified items. + public static SortedDictionary SortedDictionaryOf( + params KeyValuePair[] items) where TKey : notnull + { + return new SortedDictionary(DictionaryOf(items)); + } + + /// + /// Create a sorted dictionary of the specified items. + /// + /// The items which wil populate the sorted dictionary. + /// The underlying type of the sorted dictionary key. + /// The underlying type of the sorted dictionary value. + /// Returns a sorted dictionary populated with the specified items. + public static SortedDictionary SortedDictionaryOf( + params (TKey key, TValue value)[] items) where TKey : notnull + { + return new SortedDictionary(DictionaryOf(items)); + } + + /// + /// Create an immutable sorted dictionary of the specified items. + /// + /// The items which wil populate the immutable sorted dictionary. + /// The underlying type of the immutable sorted dictionary key. + /// The underlying type of the immutable sorted dictionary value. + /// Returns an immutable sorted dictionary populated with the specified items. + public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( + params KeyValuePair[] items) where TKey : notnull + { + return SortedDictionaryOf(items).ToImmutableSortedDictionary(); + } + + /// + /// Create an immutable sorted dictionary of the specified items. + /// + /// The items which wil populate the immutable sorted dictionary. + /// The underlying type of the immutable sorted dictionary key. + /// The underlying type of the immutable sorted dictionary value. + /// Returns an immutable sorted dictionary populated with the specified items. + public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( + params (TKey key, TValue value)[] items) where TKey : notnull + { + return SortedDictionaryOf(items).ToImmutableSortedDictionary(); + } + + /// + /// Creates a hash set of the specified items. + /// + /// The items which will populate the hash set. + /// The underlying type of the hash set. + /// Returns a hash set populated with the specified items. + public static HashSet HashSetOf(params T[] items) + { + return new HashSet(items.Copy()); + } + + /// + /// Creates an immutable hash set of the specified items. + /// + /// The items which will populate the immutable hash set. + /// The underlying type of the immutable hash set. + /// Returns an immutable hash set populated with the specified items. + public static ImmutableHashSet ImmutableHashSetOf(params T[] items) + { + return HashSetOf(items).ToImmutableHashSet(); + } + + /// + /// Creates a sorted set of the specified items. + /// + /// The items which will populate the sorted set. + /// The underlying type of the sorted set. + /// Returns a sorted set populated with the specified items. + public static SortedSet SortedSetOf(params T[] items) + { + return new SortedSet(items.Copy()); + } + + /// + /// Creates an immutable sorted set of the specified items. + /// + /// The items which will populate the immutable sorted set. + /// The underlying type of the immutable sorted set. + /// Returns an immutable sorted set populated with the specified items. + public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) + { + return SortedSetOf(items).ToImmutableSortedSet(); + } + + /// + /// Creates a stack of the specified items. + /// + /// The items which will populate the stack. + /// The underlying type of the stack. + /// Returns a stack populated with the specified items. + public static Stack StackOf(params T[] items) + { + return new Stack(items.Copy()); + } + + /// + /// Creates an immutable stack of the specified items. + /// + /// The items which will populate the immutable stack. + /// The underlying type of the immutable stack. + /// Returns an immutable stack populated with the specified items. + public static ImmutableStack ImmutableStackOf(params T[] items) + { + return ImmutableStack.Create(items.Copy()); + } + + /// + /// Creates a queue of the specified items. + /// + /// The items which will populate the queue. + /// The underlying type of the queue. + /// Returns a queue populated with the specified items. + public static Queue QueueOf(params T[] items) + { + return new Queue(items.Copy()); + } + + /// + /// Creates an immutable queue of the specified items. + /// + /// The items which will populate the immutable queue. + /// The underlying type of the immutable queue. + /// Returns an immutable queue populated with the specified items. + public static ImmutableQueue ImmutableQueueOf(params T[] items) + { + return ImmutableQueue.Create(items.Copy()); + } +} diff --git a/OnixLabs.Core/Enumeration.Comparable.cs b/OnixLabs.Core/Enumeration.Comparable.cs index 964c534..99aa808 100644 --- a/OnixLabs.Core/Enumeration.Comparable.cs +++ b/OnixLabs.Core/Enumeration.Comparable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,11 +23,11 @@ public abstract partial class Enumeration : IComparable, IComparable /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the /// other object. /// - /// An object to compare with this instance. + /// An object to compare with the current instance. /// Returns a value that indicates the relative order of the objects being compared. public int CompareTo(object? obj) { - return CompareTo(obj as T); + return this.CompareObject(obj); } /// @@ -35,7 +35,7 @@ public int CompareTo(object? obj) /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the /// other object. /// - /// An object to compare with this instance. + /// An object to compare with the current instance. /// Returns a value that indicates the relative order of the objects being compared. public int CompareTo(T? other) { diff --git a/OnixLabs.Core/Enumeration.Equatable.cs b/OnixLabs.Core/Enumeration.Equatable.cs index 93b2602..f03cdb4 100644 --- a/OnixLabs.Core/Enumeration.Equatable.cs +++ b/OnixLabs.Core/Enumeration.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,32 +18,10 @@ namespace OnixLabs.Core; public abstract partial class Enumeration : IEquatable { - /// - /// Performs an equality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(Enumeration a, Enumeration b) - { - return Equals(a, b); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(Enumeration a, Enumeration b) - { - return !Equals(a, b); - } - /// /// Indicates whether the current object is equal to another object of the same type. /// - /// An object to compare with this object. + /// An object to compare with the current object. /// Returns true if the current object is equal to the other parameter; otherwise, false. public bool Equals(T? other) { @@ -55,21 +33,43 @@ public bool Equals(T? other) } /// - /// Checks for equality between this instance and another object. + /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// Returns true if the object is equal to the current instance; otherwise, false. public sealed override bool Equals(object? obj) { return Equals(obj as T); } /// - /// Serves as a hash code function for this instance. + /// Serves as a hash code function for the current instance. /// - /// A hash code for this instance. - public override int GetHashCode() + /// Returns a hash code for the current instance. + public sealed override int GetHashCode() { return HashCode.Combine(GetType(), Name, Value); } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns true if the instances are equal; otherwise, false. + public static bool operator ==(Enumeration left, Enumeration right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns true if the instances are not equal; otherwise, false. + public static bool operator !=(Enumeration left, Enumeration right) + { + return !Equals(left, right); + } } diff --git a/OnixLabs.Core/Enumeration.From.cs b/OnixLabs.Core/Enumeration.From.cs index ea7c1d9..959b92b 100644 --- a/OnixLabs.Core/Enumeration.From.cs +++ b/OnixLabs.Core/Enumeration.From.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ using System.Collections.Generic; using System.Linq; using OnixLabs.Core.Linq; -using static OnixLabs.Core.Preconditions; namespace OnixLabs.Core; @@ -32,8 +31,8 @@ public static T FromName(string name) { IEnumerable results = GetAll().Where(entry => entry.Name == name).ToArray(); - Check(results.IsNotEmpty(), $"Enumeration entry for name '{name}' not found in {typeof(T).Name}."); - Check(results.IsSingle(), $"Multiple enumeration entries for name '{name}' found in {typeof(T).Name}."); + Require(results.IsNotEmpty(), $"Enumeration entry for name '{name}' not found in {typeof(T).Name}.", nameof(name)); + Require(results.IsSingle(), $"Multiple enumeration entries for name '{name}' found in {typeof(T).Name}.", nameof(name)); return results.Single(); } @@ -48,8 +47,8 @@ public static T FromValue(int value) { IEnumerable results = GetAll().Where(entry => entry.Value == value).ToArray(); - Check(results.IsNotEmpty(), $"Enumeration entry for value '{value}' not found in {typeof(T).Name}."); - Check(results.IsSingle(), $"Multiple enumeration entries for value '{value}' found in {typeof(T).Name}."); + Require(results.IsNotEmpty(), $"Enumeration entry for value '{value}' not found in {typeof(T).Name}.", nameof(value)); + Require(results.IsSingle(), $"Multiple enumeration entries for value '{value}' found in {typeof(T).Name}.", nameof(value)); return results.Single(); } diff --git a/OnixLabs.Core/Enumeration.Get.cs b/OnixLabs.Core/Enumeration.Get.cs index 7261703..273f9df 100644 --- a/OnixLabs.Core/Enumeration.Get.cs +++ b/OnixLabs.Core/Enumeration.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ public static ImmutableHashSet GetAll() return typeof(T) .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) .Select(field => field.GetValue(null)) - .WhereIs() + .WhereInstanceOf() .ToImmutableHashSet(); } @@ -60,4 +60,4 @@ public static ImmutableHashSet GetValues() { return GetAll().Select(entry => entry.Value).ToImmutableHashSet(); } -} \ No newline at end of file +} diff --git a/OnixLabs.Core/Enumeration.To.cs b/OnixLabs.Core/Enumeration.To.cs index 5432deb..9e46dad 100644 --- a/OnixLabs.Core/Enumeration.To.cs +++ b/OnixLabs.Core/Enumeration.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,9 +30,9 @@ public abstract partial class Enumeration /// /// Returns a that represents the current object. /// - /// A that represents the current object. + /// Returns a that represents the current object. public override string ToString() { return Name; } -} \ No newline at end of file +} diff --git a/OnixLabs.Core/Enumeration.cs b/OnixLabs.Core/Enumeration.cs index cf98ae2..40c6230 100644 --- a/OnixLabs.Core/Enumeration.cs +++ b/OnixLabs.Core/Enumeration.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/ArrayExtensions.cs b/OnixLabs.Core/Extensions.Array.cs similarity index 81% rename from OnixLabs.Core/ArrayExtensions.cs rename to OnixLabs.Core/Extensions.Array.cs index 67d6b4c..5900e62 100644 --- a/OnixLabs.Core/ArrayExtensions.cs +++ b/OnixLabs.Core/Extensions.Array.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,24 +24,24 @@ namespace OnixLabs.Core; public static class ArrayExtensions { /// - /// Copies this array. + /// Creates a copy of the current array. /// /// The array to copy. /// The underlying type of the array. - /// Returns an exact copy of this array. + /// Returns an exact copy of the current array. public static T[] Copy(this T[] array) { return Copy(array, 0, array.Length); } /// - /// Copies this array. + /// Creates a copy of the current array. /// /// The array to copy. /// The index of the array to begin copying from. /// The number of elements of the array to copy. /// The underlying type of the array. - /// Returns an exact copy of this array. + /// Returns an exact copy of the current array. public static T[] Copy(this T[] array, int index, int count) { T[] result = new T[count]; @@ -51,16 +51,15 @@ public static T[] Copy(this T[] array, int index, int count) } /// - /// Concatenates this array with another array. + /// Concatenates the current array with another array. /// /// The source array to concatenate with the other array. /// The other array to concatenate with the source array. /// The underlying type of the array. - /// Returns this array concatenated with the other array. + /// Returns the current array concatenated with the other array. public static T[] ConcatenateWith(this T[] array, T[] other) { - int length = array.Length + other.Length; - T[] result = new T[length]; + T[] result = new T[array.Length + other.Length]; Array.Copy(array, 0, result, 0, array.Length); Array.Copy(other, 0, result, array.Length, other.Length); diff --git a/OnixLabs.Core/Extensions.Object.cs b/OnixLabs.Core/Extensions.Object.cs new file mode 100644 index 0000000..728084a --- /dev/null +++ b/OnixLabs.Core/Extensions.Object.cs @@ -0,0 +1,59 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; + +namespace OnixLabs.Core; + +/// +/// Provides extension methods for objects. +/// +[EditorBrowsable(EditorBrowsableState.Never)] +public static class ObjectExtensions +{ + /// + /// Provides a mechanism to compare the current to compare to the specified object. + /// + /// The current to compare to the specified object. + /// The to compare to the current . + /// The underlying type of the current . + /// Returns a value that indicates the relative order of the objects being compared. + /// If the specified object is not null, or of the specified type. + public static int CompareObject(this IComparable comparable, object? obj) + { + if (obj is null) return 1; + if (obj is T other) return comparable.CompareTo(other); + throw new ArgumentException($"Object must be of type {typeof(T).Name}", nameof(obj)); + } + + /// + /// Gets the representation of the current formatted as a record. + /// + /// The to format as a record. + /// Returns the representation of the current formatted as a record. + public static string ToRecordString(this object value) + { + Type type = value.GetType(); + + IEnumerable properties = type + .GetProperties(BindingFlags.Public | BindingFlags.Instance) + .Select(property => $"{property.Name} = {property.GetValue(value)}"); + + return $"{type.Name} {{ {string.Join(", ", properties)} }}"; + } +} diff --git a/OnixLabs.Core/StringExtensions.cs b/OnixLabs.Core/Extensions.String.cs similarity index 74% rename from OnixLabs.Core/StringExtensions.cs rename to OnixLabs.Core/Extensions.String.cs index 6be0262..d2db538 100644 --- a/OnixLabs.Core/StringExtensions.cs +++ b/OnixLabs.Core/Extensions.String.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,7 +13,10 @@ // limitations under the License. using System; +using System.Collections.Generic; using System.ComponentModel; +using System.Globalization; +using System.Linq; using System.Text; namespace OnixLabs.Core; @@ -29,6 +32,19 @@ public static class StringExtensions /// private const int IndexNotFound = -1; + /// + /// Repeats the current by the specified number of repetitions. + /// + /// The value to repeat. + /// The specified number of repetitions to repeat by. + /// Returns a new containing the repeated value. + public static string Repeat(this string value, int count) + { + if (count <= 0) return string.Empty; + IEnumerable repetitions = Enumerable.Repeat(value, count); + return string.Join(string.Empty, repetitions); + } + /// /// Returns a substring before the first occurrence of the specified delimiter. /// @@ -36,7 +52,7 @@ public static class StringExtensions /// The delimiter to find within the original string. /// The value to return if the delimiter is not found, which defaults to the original string. /// Returns a substring before the first occurrence of the specified delimiter. - public static string SubstringBefore(this string value, char delimiter, string? defaultValue = null) + public static string SubstringBeforeFirst(this string value, char delimiter, string? defaultValue = null) { int index = value.IndexOf(delimiter); @@ -55,7 +71,7 @@ public static string SubstringBefore(this string value, char delimiter, string? /// The value to return if the delimiter is not found, which defaults to the original string. /// Specifies the string comparison rule for the search. /// Returns a substring before the first occurrence of the specified delimiter. - public static string SubstringBefore( + public static string SubstringBeforeFirst( this string value, string delimiter, string? defaultValue = null, @@ -118,7 +134,7 @@ public static string SubstringBeforeLast( /// The delimiter to find within the original string. /// The value to return if the delimiter is not found, which defaults to the original string. /// Returns a substring after the first occurrence of the specified delimiter. - public static string SubstringAfter(this string value, char delimiter, string? defaultValue = null) + public static string SubstringAfterFirst(this string value, char delimiter, string? defaultValue = null) { int index = value.IndexOf(delimiter); @@ -137,7 +153,7 @@ public static string SubstringAfter(this string value, char delimiter, string? d /// The value to return if the delimiter is not found, which defaults to the original string. /// Specifies the string comparison rule for the search. /// Returns a substring after the first occurrence of the specified delimiter. - public static string SubstringAfter( + public static string SubstringAfterFirst( this string value, string delimiter, string? defaultValue = null, @@ -214,6 +230,42 @@ public static byte[] ToByteArray(this string value, Encoding encoding) return encoding.GetBytes(value); } + /// + /// Converts the current to a . + /// + /// The original from which to obtain a . + /// An object that supplies culture-specific formatting information. + /// A bitwise combination of the enumeration values that indicates the style elements that can be present. + /// Returns a parsed from the current value. + public static DateTime ToDateTime(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DateTimeStyles.None) + { + return DateTime.Parse(value, provider, styles); + } + + /// + /// Converts the current to a . + /// + /// The original from which to obtain a . + /// An object that supplies culture-specific formatting information. + /// A bitwise combination of the enumeration values that indicates the style elements that can be present. + /// Returns a parsed from the current value. + public static DateOnly ToDateOnly(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DateTimeStyles.None) + { + return DateOnly.Parse(value, provider, styles); + } + + /// + /// Converts the current to a . + /// + /// The original from which to obtain a . + /// An object that supplies culture-specific formatting information. + /// A bitwise combination of the enumeration values that indicates the style elements that can be present. + /// Returns a parsed from the current value. + public static TimeOnly ToTimeOnly(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DateTimeStyles.None) + { + return TimeOnly.Parse(value, provider, styles); + } + /// /// Converts the current between the specified before and after values. /// diff --git a/OnixLabs.Core/HashCodeExtensions.cs b/OnixLabs.Core/HashCodeExtensions.cs deleted file mode 100644 index b22c40f..0000000 --- a/OnixLabs.Core/HashCodeExtensions.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2020-2022 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using OnixLabs.Core.Linq; - -namespace OnixLabs.Core; - -/// -/// Provides extension methods for hash codes. -/// -[EditorBrowsable(EditorBrowsableState.Never)] -public static class HashCodeExtensions -{ - /// - /// Adds an item to be hashed into a instance. - /// - /// The which will receive the item to hash. - /// The item to hash into the . - /// The underlying type of the item to hash. - /// Returns the containing the added item. - public static HashCode AddItem(this HashCode hashCode, T item) - { - hashCode.Add(item); - return hashCode; - } - - /// - /// Adds the items to be hashed into a instance. - /// - /// The which will receive the items to hash. - /// The items to hash into the . - /// The underlying type of the items to hash. - /// Returns the containing the added items. - public static HashCode AddItems(this HashCode hashCode, IEnumerable items) - { - items.ForEach(hashCode.Add); - return hashCode; - } -} diff --git a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs new file mode 100644 index 0000000..240f409 --- /dev/null +++ b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs @@ -0,0 +1,246 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Numerics; + +namespace OnixLabs.Core.Linq; + +/// +/// Provides LINQ-like extension methods for . +/// +// ReSharper disable InconsistentNaming +[EditorBrowsable(EditorBrowsableState.Never)] +public static class IEnumerableExtensions +{ + /// + /// Determines whether all elements of the current are equal by a specified property. + /// + /// The on which to perform the operation. + /// The selector function which will be used to select each property from each element. + /// The underlying type of the . + /// The underlying type of each selected element. + /// Returns true if all selected element properties are equal; otherwise false. + public static bool AllEqualBy(this IEnumerable enumerable, Func selector) + { + ISet elements = enumerable.Select(selector).ToHashSet(); + return elements.IsNotEmpty() && elements.IsSingle(); + } + + /// + /// Determines whether any elements of the current are equal by a specified property. + /// + /// The on which to perform the operation. + /// The selector function which will be used to select each property from each element. + /// The underlying type of the . + /// The underlying type of each selected element. + /// Returns true if any selected element properties are equal; otherwise false. + public static bool AnyEqualBy(this IEnumerable enumerable, Func selector) + { + IList elements = enumerable.Select(selector).ToList(); + ISet distinctElements = elements.ToHashSet(); + return distinctElements.IsNotEmpty() && distinctElements.Count < elements.Count; + } + + /// + /// Obtains a number that represents how many elements in the the current do not satisfy the specified predicate condition. + /// + /// The on which to perform the operation. + /// The function to test each element for a condition. + /// The underlying type of the . + /// Returns a number that represents how many elements in the the current do not satisfy the specified predicate condition. + public static int CountNot(this IEnumerable enumerable, Func predicate) + { + return enumerable.Count(element => !predicate(element)); + } + + /// + /// Performs the specified for each element of the current . + /// + /// The over which to iterate. + /// The to perform for each element. + /// The underlying type of the . + public static void ForEach(this IEnumerable enumerable, Action action) + { + foreach (T element in enumerable) action(element); + } + + /// + /// Gets the content hash code of the elements of the current . + /// + /// The from which to compute a content hash code. + /// The underlying type of the . + /// Returns the computed content hash code of the current . + public static int GetContentHashCode(this IEnumerable enumerable) + { + HashCode hashCode = new(); + enumerable.ForEach(item => hashCode.Add(item)); + return hashCode.ToHashCode(); + } + + /// + /// Determines whether the current is empty. + /// + /// The on which to perform the operation. + /// he underlying type of the . + /// Returns true if the is empty; otherwise, false. + public static bool IsEmpty(this IEnumerable enumerable) + { + return !enumerable.Any(); + } + + /// + /// Determines whether the current is not empty. + /// + /// The on which to perform the operation. + /// The underlying type of the . + /// Returns true if the is not empty; otherwise, false. + public static bool IsNotEmpty(this IEnumerable enumerable) + { + return !enumerable.IsEmpty(); + } + + /// + /// Determines whether the current contains a single element. + /// + /// The on which to perform the operation. + /// The underlying type of the . + /// Returns true if the contains a single element; otherwise, false. + public static bool IsSingle(this IEnumerable enumerable) + { + return enumerable.LongCount() == 1; + } + + /// + /// Determines whether the current contains an even number of elements. + /// + /// The on which to perform the operation. + /// The underlying type of the . + /// Returns true if the contains an even number of elements; otherwise, false. + public static bool IsCountEven(this IEnumerable enumerable) + { + return enumerable.LongCount() % 2 == 0; + } + + /// + /// Determines whether the current contains an odd number of elements. + /// + /// The on which to perform the operation. + /// The underlying type of the . + /// Returns true if the contains an odd number of elements; otherwise, false. + public static bool IsCountOdd(this IEnumerable enumerable) + { + return !enumerable.IsCountEven(); + } + + /// + /// Joins the elements of the current into a . + /// + /// The to join. + /// The underlying type of the . + /// Returns the elements of the current , joined into a string. + public static string JoinToString(this IEnumerable enumerable) + { + return enumerable.JoinToString(", "); + } + + /// + /// Joins the elements of the current into a . + /// + /// The to join. + /// The separator which will appear between joined elements. + /// The underlying type of the . + /// Returns the elements of the current , joined into a string. + public static string JoinToString(this IEnumerable enumerable, string separator) + { + return string.Join(separator, enumerable); + } + + /// + /// Determines whether none of the elements of the current satisfy the specified predicate condition. + /// + /// The on which to perform the operation. + /// The function to test each element for a condition. + /// The underlying type of the . + /// Returns true if none of the elements of the current satisfy the specified predicate condition; otherwise, false. + public static bool None(this IEnumerable enumerable, Func predicate) + { + return !enumerable.Any(predicate); + } + + /// + /// Calculates the sum of the elements of the current . + /// + /// The to sum. + /// The underlying type of the . + /// Returns the sum of the elements of the current . + public static T Sum(this IEnumerable enumerable) where T : INumber + { + IEnumerable elements = enumerable.ToArray(); + return elements.IsEmpty() ? T.Zero : elements.Aggregate((left, right) => left + right); + } + + /// + /// Calculates the sum of the elements of the current . + /// + /// The to sum. + /// The selector function which will be used to select each property from each element. + /// The underlying type of the . + /// The underlying type of each element to sum. + /// Returns the sum of the elements of the current . + public static TResult SumBy(this IEnumerable enumerable, Func selector) where TResult : INumber + { + return enumerable.Select(selector).Sum(); + } + + /// + /// Filters the current to only elements of the specified type. + /// + /// The on which to perform the operation. + /// The underlying type of the . + /// Returns a new containing only elements of the specified type. + public static IEnumerable WhereInstanceOf(this IEnumerable enumerable) + { + foreach (object? element in enumerable) + { + if (element is T elementOfType) yield return elementOfType; + } + } + + /// + /// Filters the current elements that do not satisfy the specified predicate condition. + /// + /// The on which to perform the operation. + /// The function to test each element for a condition. + /// The underlying type of the . + /// Returns a new that contains elements that do not satisfy the condition. + public static IEnumerable WhereNot(this IEnumerable enumerable, Func predicate) + { + return enumerable.Where(element => !predicate(element)); + } + + /// + /// Filters the current elements that are not null. + /// + /// The on which to perform the operation. + /// The underlying type of the . + /// Returns a new that contains elements that are not null. + public static IEnumerable WhereNotNull(this IEnumerable enumerable) + { + return enumerable.Where(element => element is not null)!; + } +} diff --git a/OnixLabs.Core/Linq/IEnumerableExtensions.cs b/OnixLabs.Core/Linq/IEnumerableExtensions.cs deleted file mode 100644 index d082232..0000000 --- a/OnixLabs.Core/Linq/IEnumerableExtensions.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2020-2022 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// ReSharper disable InconsistentNaming - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; - -namespace OnixLabs.Core.Linq; - -/// -/// Provides LINQ-like extension methods for . -/// -[EditorBrowsable(EditorBrowsableState.Never)] -public static class IEnumerableExtensions -{ - /// - /// Determines whether all elements of this are equal by a specified property. - /// - /// The on which to perform the operation. - /// The selector function which will be used to select each property from each element. - /// The underlying type of the . - /// The underlying type of each selected element. - /// Returns true if all selected element properties are equal; otherwise false. - public static bool AllEqualBy(this IEnumerable enumerable, Func selector) - { - IEnumerable elements = enumerable.ToArray(); - - if (elements.IsEmpty()) - { - return false; - } - - if (elements.IsSingle()) - { - return true; - } - - TProperty first = selector(elements.First()); - return elements.All(element => Equals(first, selector(element))); - } - - /// - /// Determines whether any elements of this are equal by a specified property. - /// - /// The on which to perform the operation. - /// The selector function which will be used to select each property from each element. - /// The underlying type of the . - /// The underlying type of each selected element. - /// Returns true if any selected element properties are equal; otherwise false. - public static bool AnyEqualBy(this IEnumerable enumerable, Func selector) - { - IEnumerable elements = enumerable.ToArray(); - - if (elements.IsEmpty()) - { - return false; - } - - if (elements.IsSingle()) - { - return true; - } - - TProperty first = selector(elements.First()); - return elements.Any(element => Equals(first, selector(element))); - } - - /// - /// Performs the specified for each element of this . - /// - /// The over which to iterate. - /// The to perform for each element. - /// The underlying type of the . - public static void ForEach(this IEnumerable enumerable, Action action) - { - foreach (T element in enumerable) - { - action(element); - } - } - - /// - /// Gets the content hash code of the elements of this . - /// - /// The from which to compute a content hash code. - /// The underlying type of the . - /// Returns the computed content hash code of this . - public static int GetContentHashCode(this IEnumerable enumerable) - { - return new HashCode().AddItems(enumerable).ToHashCode(); - } - - /// - /// Determines whether this is empty. - /// - /// The on which to perform the operation. - /// he underlying type of the . - /// Returns true if the is empty; otherwise, false. - public static bool IsEmpty(this IEnumerable enumerable) - { - return !enumerable.Any(); - } - - /// - /// Determines whether this is not empty. - /// - /// The on which to perform the operation. - /// The underlying type of the . - /// Returns true if the is not empty; otherwise, false. - public static bool IsNotEmpty(this IEnumerable enumerable) - { - return !enumerable.IsEmpty(); - } - - /// - /// Determines whether this contains a single element. - /// - /// The on which to perform the operation. - /// The underlying type of the . - /// Returns true if the contains a single element; otherwise, false. - public static bool IsSingle(this IEnumerable enumerable) - { - return enumerable.LongCount() == 1; - } - - /// - /// Determines whether this contains an even number of elements. - /// - /// The on which to perform the operation. - /// The underlying type of the . - /// Returns true if the contains an even number of elements; otherwise, false. - public static bool IsCountEven(this IEnumerable enumerable) - { - return enumerable.LongCount() % 2 == 0; - } - - /// - /// Determines whether this contains an odd number of elements. - /// - /// The on which to perform the operation. - /// The underlying type of the . - /// Returns true if the contains an odd number of elements; otherwise, false. - public static bool IsCountOdd(this IEnumerable enumerable) - { - return !enumerable.IsCountEven(); - } - - /// - /// Filters this to only elements of the specified type. - /// - /// The on which to perform the operation. - /// The underlying type of the . - /// Returns a new containing only elements of the specified type. - public static IEnumerable WhereIs(this IEnumerable enumerable) - { - foreach (object? element in enumerable) - { - if (element is T elementOfType) - { - yield return elementOfType; - } - } - } -} diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj index 69d849f..b20b35e 100644 --- a/OnixLabs.Core/OnixLabs.Core.csproj +++ b/OnixLabs.Core/OnixLabs.Core.csproj @@ -1,28 +1,33 @@ - net6.0 - 10 + net7.0 + 11 enable true OnixLabs.Core ONIXLabs ONIXLabs Core API for .NET - 5.0.0 + 6.0.0 en - Copyright © ONIXLabs 2020-2022 + Copyright © ONIXLabs 2020-2023 https://github.com/onix-labs/onixlabs-dotnet - 5.0.0 + 6.0.0 - true - bin\Debug\net5.0\OnixLabs.Core.xml + true + bin\Debug\net5.0\OnixLabs.Core.xml - bin\Release\net5.0\OnixLabs.Core.xml - true + bin\Release\net5.0\OnixLabs.Core.xml + true + + + + + diff --git a/OnixLabs.Core/Preconditions.cs b/OnixLabs.Core/Preconditions.cs index e38c4ac..c9295c4 100644 --- a/OnixLabs.Core/Preconditions.cs +++ b/OnixLabs.Core/Preconditions.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,35 +25,54 @@ public static class Preconditions /// /// Performs a general pre-condition check, which fails if the condition returns false. /// - /// The condition to check. + /// The condition to check. /// The exception message to throw in the event that the condition fails. - /// The name of the parameter which is invalid. - /// If the condition fails. + /// If the condition fails. [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static void Check(bool value, string message = "Argument check failed.", string? paramName = null) + public static void Check(bool condition, string message = "Check failed.") { - if (!value) - { - throw new ArgumentException(message, paramName); - } + if (!condition) throw new InvalidOperationException(message); } /// - /// Performs a general pre-condition check that the specified value is not null, which fails if the value is null. + /// Performs a general pre-condition requirement that the specified value is not null, which fails if the value is null. /// /// The nullable value to check. /// The exception message to throw in the event that the condition fails. - /// The underlying type of the value to check. + /// The underlying type of the value. /// Returns the specified value as non-nullable in the event that the value is not null. - /// If the condition fails and the value is null. + /// If the condition fails because the value is null. [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static T CheckNotNull(T? value, string message = "Argument null checked failed.") where T : notnull + public static T CheckNotNull(T? value, string message = "Null check failed.") where T : notnull { - if (value is null) - { - throw new ArgumentNullException(message); - } + return value ?? throw new InvalidOperationException(message); + } - return value; + /// + /// Performs a general pre-condition requirement, which fails if the condition returns false. + /// + /// The condition of the requirement. + /// The exception message to throw in the event that the condition fails. + /// The name of the parameter which is invalid. + /// If the condition fails. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void Require(bool condition, string message = "Argument requirement failed.", string? parameterName = null) + { + if (!condition) throw new ArgumentException(message, parameterName); + } + + /// + /// Performs a general pre-condition requirement that the specified value is not null, which fails if the value is null. + /// + /// The nullable value to check. + /// The exception message to throw in the event that the condition fails. + /// The name of the parameter which is invalid. + /// The underlying type of the value. + /// Returns the specified value as non-nullable in the event that the value is not null. + /// If the condition fails because the value is null. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static T RequireNotNull(T? value, string message = "Argument must be null.", string? parameterName = null) where T : notnull + { + return value ?? throw new ArgumentNullException(message, parameterName); } } diff --git a/OnixLabs.Core/Reflection/Extensions.Type.cs b/OnixLabs.Core/Reflection/Extensions.Type.cs new file mode 100644 index 0000000..9a26dd6 --- /dev/null +++ b/OnixLabs.Core/Reflection/Extensions.Type.cs @@ -0,0 +1,61 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; + +namespace OnixLabs.Core.Reflection; + +/// +/// Provides extension methods for types. +/// +[EditorBrowsable(EditorBrowsableState.Never)] +public static class TypeExtensions +{ + /// + /// The identifier marker than indicates a generic type. + /// + private const char GenericTypeIdentifierMarker = '`'; + + /// + /// Gets the simple type name from the specified type, excluding any generic type parameters. + /// + /// The from which to obtain a simple type name. + /// Returns the simple type name from the specified type, excluding any generic type parameters. + public static string GetSimpleName(this Type type) + { + return type.Name.SubstringBeforeFirst(GenericTypeIdentifierMarker); + } + + /// + /// Gets the formatted type name from the specified type, including any generic type parameters. + /// + /// The from which to obtain a formatted type name. + /// Returns the formatted type name from the specified type, including any generic type parameters. + public static string GetFormattedName(this Type type) + { + if (!type.Name.Contains(GenericTypeIdentifierMarker)) + { + return type.Name; + } + + IEnumerable genericTypeArguments = type.GenericTypeArguments.Select(GetFormattedName); + string typeName = type.Name.SubstringBeforeFirst(GenericTypeIdentifierMarker); + string generics = string.Join(", ", genericTypeArguments).Wrap("<", ">"); + + return typeName + generics; + } +} diff --git a/OnixLabs.Core/Text/Base16.Empty.cs b/OnixLabs.Core/Text/Base16.Constants.cs similarity index 68% rename from OnixLabs.Core/Text/Base16.Empty.cs rename to OnixLabs.Core/Text/Base16.Constants.cs index c059b38..181b936 100644 --- a/OnixLabs.Core/Text/Base16.Empty.cs +++ b/OnixLabs.Core/Text/Base16.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,22 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; +using OnixLabs.Core.Collections; namespace OnixLabs.Core.Text; public readonly partial struct Base16 { /// - /// Gets an empty Base-16 value. + /// Gets an empty value. /// - public static readonly Base16 Empty; - - /// - /// Initializes static members of the class. - /// - static Base16() - { - Empty = FromByteArray(Array.Empty()); - } + public static Base16 Empty => Create(Collection.EmptyArray()); } diff --git a/OnixLabs.Core/Text/Base16.Create.cs b/OnixLabs.Core/Text/Base16.Create.cs new file mode 100644 index 0000000..3a5dbb6 --- /dev/null +++ b/OnixLabs.Core/Text/Base16.Create.cs @@ -0,0 +1,54 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Text; + +namespace OnixLabs.Core.Text; + +public readonly partial struct Base16 +{ + /// + /// Creates a instance from the specified array. + /// + /// The underlying value. + /// Returns a new instance. + public static Base16 Create(byte[] value) + { + return new Base16(value); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// Returns a new instance. + public static Base16 Create(ReadOnlySpan value) + { + return Create(value, Encoding.Default); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The encoding to use to obtain the underlying value. + /// Returns a new instance. + public static Base16 Create(ReadOnlySpan value, Encoding encoding) + { + // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. + byte[] bytes = encoding.GetBytes(value.ToArray()); + return Create(bytes); + } +} diff --git a/OnixLabs.Core/Text/Base16.Equatable.cs b/OnixLabs.Core/Text/Base16.Equatable.cs index e4d923f..06509a2 100644 --- a/OnixLabs.Core/Text/Base16.Equatable.cs +++ b/OnixLabs.Core/Text/Base16.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,56 +18,56 @@ namespace OnixLabs.Core.Text; -public readonly partial struct Base16 : IEquatable +public readonly partial struct Base16 { /// - /// Performs an equality check between two object instances. + /// Checks for equality between the current instance and another object. /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(Base16 a, Base16 b) + /// The object to check for equality. + /// Returns true if the object is equal to the current instance; otherwise, false. + public bool Equals(Base16 other) { - return Equals(a, b); + return other.Value.SequenceEqual(Value); } /// - /// Performs an inequality check between two object instances. + /// Checks for equality between the current instance and another object. /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(Base16 a, Base16 b) + /// The object to check for equality. + /// Returns true if the object is equal to the current instance; otherwise, false. + public override bool Equals(object? obj) { - return !Equals(a, b); + return obj is Base16 other && Equals(other); } /// - /// Checks for equality between this instance and another object. + /// Serves as a hash code function for the current instance. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public bool Equals(Base16 other) + /// Returns a hash code for the current instance. + public override int GetHashCode() { - return other.Value.SequenceEqual(Value); + return HashCode.Combine(Value.GetContentHashCode()); } /// - /// Checks for equality between this instance and another object. + /// Performs an equality check between two object instances. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public override bool Equals(object? obj) + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns true if the instances are equal; otherwise, false. + public static bool operator ==(Base16 left, Base16 right) { - return obj is Base16 other && Equals(other); + return Equals(left, right); } /// - /// Serves as a hash code function for this instance. + /// Performs an inequality check between two object instances. /// - /// A hash code for this instance. - public override int GetHashCode() + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns true if the instances are not equal; otherwise, false. + public static bool operator !=(Base16 left, Base16 right) { - return HashCode.Combine(Value.GetContentHashCode()); + return !Equals(left, right); } } diff --git a/OnixLabs.Core/Text/Base16.From.cs b/OnixLabs.Core/Text/Base16.From.cs deleted file mode 100644 index 361de10..0000000 --- a/OnixLabs.Core/Text/Base16.From.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2020-2022 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base16 -{ - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Returns a new instance. - public static Base16 FromByteArray(byte[] value) - { - return new Base16(value); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Returns a new instance. - public static Base16 FromCharArray(char[] value) - { - return FromCharArray(value, Encoding.Default); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base16 FromCharArray(char[] value, Encoding encoding) - { - byte[] bytes = encoding.GetBytes(value); - return FromByteArray(bytes); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Returns a new instance. - public static Base16 FromSpan(ReadOnlySpan value) - { - return FromSpan(value, Encoding.Default); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base16 FromSpan(ReadOnlySpan value, Encoding encoding) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Returns a new instance. - public static Base16 FromString(string value) - { - return FromString(value, Encoding.Default); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base16 FromString(string value, Encoding encoding) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding); - } -} diff --git a/OnixLabs.Core/Text/Base16.Parse.cs b/OnixLabs.Core/Text/Base16.Parse.cs index 5ce2028..7df68a0 100644 --- a/OnixLabs.Core/Text/Base16.Parse.cs +++ b/OnixLabs.Core/Text/Base16.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,28 +18,6 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base16 { - /// - /// Parses a Base-16 (hexadecimal) value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// Returns a new instance. - public static Base16 Parse(string value) - { - ReadOnlySpan characters = value.AsSpan(); - return Parse(characters); - } - - /// - /// Parses a Base-16 (hexadecimal) value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// Returns a new instance. - public static Base16 Parse(char[] value) - { - ReadOnlySpan characters = value.AsSpan(); - return Parse(characters); - } - /// /// Parses a Base-16 (hexadecimal) value into a instance. /// @@ -48,6 +26,6 @@ public static Base16 Parse(char[] value) public static Base16 Parse(ReadOnlySpan value) { byte[] bytes = Convert.FromHexString(value); - return FromByteArray(bytes); + return Create(bytes); } } diff --git a/OnixLabs.Core/Text/Base16.To.cs b/OnixLabs.Core/Text/Base16.To.cs index f26ab6b..1451088 100644 --- a/OnixLabs.Core/Text/Base16.To.cs +++ b/OnixLabs.Core/Text/Base16.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -50,7 +50,7 @@ public string ToPlainTextString(Encoding encoding) /// /// Returns a that represents the current object. /// - /// A that represents the current object. + /// Returns a that represents the current object. public override string ToString() { return Convert.ToHexString(Value).ToLower(); diff --git a/OnixLabs.Core/Text/Base16.cs b/OnixLabs.Core/Text/Base16.cs index bf6bbcc..459c558 100644 --- a/OnixLabs.Core/Text/Base16.cs +++ b/OnixLabs.Core/Text/Base16.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ namespace OnixLabs.Core.Text; /// /// Represents a Base-16 (hexadecimal) value. /// -public readonly partial struct Base16 +public readonly partial struct Base16 : IBase { /// /// Initializes a new instance of the struct. @@ -25,7 +25,7 @@ public readonly partial struct Base16 /// The underlying value. private Base16(byte[] value) { - Value = value; + Value = value.Copy(); } /// diff --git a/OnixLabs.Core/Text/Base32.Codec.cs b/OnixLabs.Core/Text/Base32.Codec.cs index 254c197..0923f48 100644 --- a/OnixLabs.Core/Text/Base32.Codec.cs +++ b/OnixLabs.Core/Text/Base32.Codec.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -55,7 +55,7 @@ private static string Encode(byte[] value, string alphabet, bool padding) int availableBits = Math.Min(InputSize - inputSubPosition, OutputSize - outputSubPosition); outputPosition <<= availableBits; - outputPosition |= (byte) (value[inputPosition] >> (InputSize - (inputSubPosition + availableBits))); + outputPosition |= (byte)(value[inputPosition] >> (InputSize - (inputSubPosition + availableBits))); inputSubPosition += availableBits; if (inputSubPosition >= InputSize) @@ -134,7 +134,7 @@ private static byte[] Decode(ReadOnlySpan value, string alphabet, bool pad int availableBits = Math.Min(OutputSize - inputSubPosition, InputSize - outputSubPosition); outputBytes[outputPosition] <<= availableBits; - outputBytes[outputPosition] |= (byte) (index >> (OutputSize - (inputSubPosition + availableBits))); + outputBytes[outputPosition] |= (byte)(index >> (OutputSize - (inputSubPosition + availableBits))); outputSubPosition += availableBits; if (outputSubPosition >= InputSize) diff --git a/OnixLabs.Core/Text/Base32.Empty.cs b/OnixLabs.Core/Text/Base32.Constants.cs similarity index 69% rename from OnixLabs.Core/Text/Base32.Empty.cs rename to OnixLabs.Core/Text/Base32.Constants.cs index 6f5006d..36fcda5 100644 --- a/OnixLabs.Core/Text/Base32.Empty.cs +++ b/OnixLabs.Core/Text/Base32.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,22 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; +using OnixLabs.Core.Collections; namespace OnixLabs.Core.Text; public readonly partial struct Base32 { /// - /// Gets an empty Base-32 value. + /// Gets the default padding option when creating new Base-32 instances. /// - public static readonly Base32 Empty; + private const bool DefaultPadding = true; /// - /// Initializes static members of the class. + /// Gets an empty value. /// - static Base32() - { - Empty = FromByteArray(Array.Empty()); - } + public static Base32 Empty => Create(Collection.EmptyArray()); } diff --git a/OnixLabs.Core/Text/Base32.Create.cs b/OnixLabs.Core/Text/Base32.Create.cs new file mode 100644 index 0000000..e0c7cb3 --- /dev/null +++ b/OnixLabs.Core/Text/Base32.Create.cs @@ -0,0 +1,159 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Text; + +namespace OnixLabs.Core.Text; + +public readonly partial struct Base32 +{ + /// + /// Creates a instance from the specified array. + /// + /// The underlying value. + /// Returns a new instance. + public static Base32 Create(byte[] value) + { + return Create(value, Base32Alphabet.Default); + } + + /// + /// Creates a instance from the specified array. + /// + /// The underlying value. + /// The alphabet that will be used for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(byte[] value, Base32Alphabet alphabet) + { + return Create(value, alphabet, DefaultPadding); + } + + /// + /// Creates a instance from the specified array. + /// + /// The underlying value. + /// Determines whether padding should be applied for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(byte[] value, bool padding) + { + return Create(value, Base32Alphabet.Default, padding); + } + + /// + /// Creates a instance from the specified array. + /// + /// The underlying value. + /// The alphabet that will be used for Base-32 encoding and decoding operations. + /// Determines whether padding should be applied for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(byte[] value, Base32Alphabet alphabet, bool padding) + { + return new Base32(value, alphabet, padding); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// Returns a new instance. + public static Base32 Create(ReadOnlySpan value) + { + return Create(value, Encoding.Default, Base32Alphabet.Default, DefaultPadding); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The encoding to use to obtain the underlying value. + /// Returns a new instance. + public static Base32 Create(ReadOnlySpan value, Encoding encoding) + { + return Create(value, encoding, Base32Alphabet.Default, DefaultPadding); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// Determines whether padding should be applied for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(ReadOnlySpan value, bool padding) + { + return Create(value, Encoding.Default, Base32Alphabet.Default, padding); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The encoding to use to obtain the underlying value. + /// Determines whether padding should be applied for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(ReadOnlySpan value, Encoding encoding, bool padding) + { + return Create(value, encoding, Base32Alphabet.Default, padding); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The alphabet that will be used for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(ReadOnlySpan value, Base32Alphabet alphabet) + { + return Create(value, Encoding.Default, alphabet); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The encoding to use to obtain the underlying value. + /// The alphabet that will be used for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(ReadOnlySpan value, Encoding encoding, Base32Alphabet alphabet) + { + return Create(value, encoding, alphabet, DefaultPadding); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The alphabet that will be used for Base-32 encoding and decoding operations. + /// Determines whether padding should be applied for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(ReadOnlySpan value, Base32Alphabet alphabet, bool padding) + { + return Create(value, Encoding.Default, alphabet, padding); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The encoding to use to obtain the underlying value. + /// The alphabet that will be used for Base-32 encoding and decoding operations. + /// Determines whether padding should be applied for Base-32 encoding and decoding operations. + /// Returns a new instance. + public static Base32 Create(ReadOnlySpan value, Encoding encoding, Base32Alphabet alphabet, bool padding) + { + // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. + byte[] bytes = encoding.GetBytes(value.ToArray()); + return Create(bytes, alphabet, padding); + } +} diff --git a/OnixLabs.Core/Text/Base32.Equatable.cs b/OnixLabs.Core/Text/Base32.Equatable.cs index ebdd552..2110ab5 100644 --- a/OnixLabs.Core/Text/Base32.Equatable.cs +++ b/OnixLabs.Core/Text/Base32.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,56 +18,56 @@ namespace OnixLabs.Core.Text; -public readonly partial struct Base32 : IEquatable +public readonly partial struct Base32 { /// - /// Performs an equality check between two object instances. + /// Checks for equality between the current instance and another object. /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(Base32 a, Base32 b) + /// The object to check for equality. + /// Returns true if the object is equal to the current instance; otherwise, false. + public bool Equals(Base32 other) { - return Equals(a, b); + return other.Value.SequenceEqual(Value) && other.Alphabet == Alphabet && other.Padding == Padding; } /// - /// Performs an inequality check between two object instances. + /// Checks for equality between the current instance and another object. /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(Base32 a, Base32 b) + /// The object to check for equality. + /// Returns true if the object is equal to the current instance; otherwise, false. + public override bool Equals(object? obj) { - return !Equals(a, b); + return obj is Base32 other && Equals(other); } /// - /// Checks for equality between this instance and another object. + /// Serves as a hash code function for the current instance. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public bool Equals(Base32 other) + /// Returns a hash code for the current instance. + public override int GetHashCode() { - return other.Value.SequenceEqual(Value) && other.Alphabet == Alphabet && other.Padding == Padding; + return HashCode.Combine(Value.GetContentHashCode()); } /// - /// Checks for equality between this instance and another object. + /// Performs an equality check between two object instances. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public override bool Equals(object? obj) + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(Base32 left, Base32 right) { - return obj is Base32 other && Equals(other); + return Equals(left, right); } /// - /// Serves as a hash code function for this instance. + /// Performs an inequality check between two object instances. /// - /// A hash code for this instance. - public override int GetHashCode() + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(Base32 left, Base32 right) { - return HashCode.Combine(Value.GetContentHashCode()); + return !Equals(left, right); } } diff --git a/OnixLabs.Core/Text/Base32.From.cs b/OnixLabs.Core/Text/Base32.From.cs deleted file mode 100644 index 0105180..0000000 --- a/OnixLabs.Core/Text/Base32.From.cs +++ /dev/null @@ -1,349 +0,0 @@ -// Copyright 2020-2022 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base32 -{ - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Returns a new instance. - public static Base32 FromByteArray(byte[] value) - { - return FromByteArray(value, Base32Alphabet.Default); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromByteArray(byte[] value, Base32Alphabet alphabet) - { - return FromByteArray(value, alphabet, true); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromByteArray(byte[] value, bool padding) - { - return FromByteArray(value, Base32Alphabet.Default, padding); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromByteArray(byte[] value, Base32Alphabet alphabet, bool padding) - { - return new Base32(value, alphabet, padding); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Returns a new instance. - public static Base32 FromCharArray(char[] value) - { - return FromCharArray(value, Encoding.Default, Base32Alphabet.Default, true); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base32 FromCharArray(char[] value, Encoding encoding) - { - return FromCharArray(value, encoding, Base32Alphabet.Default, true); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromCharArray(char[] value, bool padding) - { - return FromCharArray(value, Encoding.Default, Base32Alphabet.Default, padding); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromCharArray(char[] value, Encoding encoding, bool padding) - { - return FromCharArray(value, encoding, Base32Alphabet.Default, padding); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromCharArray(char[] value, Base32Alphabet alphabet) - { - return FromCharArray(value, Encoding.Default, alphabet); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromCharArray(char[] value, Encoding encoding, Base32Alphabet alphabet) - { - byte[] bytes = encoding.GetBytes(value); - return FromByteArray(bytes, alphabet); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromCharArray(char[] value, Base32Alphabet alphabet, bool padding) - { - return FromCharArray(value, Encoding.Default, alphabet, padding); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromCharArray(char[] value, Encoding encoding, Base32Alphabet alphabet, bool padding) - { - byte[] bytes = encoding.GetBytes(value); - return FromByteArray(bytes, alphabet, padding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Returns a new instance. - public static Base32 FromSpan(ReadOnlySpan value) - { - return FromSpan(value, Encoding.Default, Base32Alphabet.Default, true); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base32 FromSpan(ReadOnlySpan value, Encoding encoding) - { - return FromSpan(value, encoding, Base32Alphabet.Default, true); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromSpan(ReadOnlySpan value, bool padding) - { - return FromSpan(value, Encoding.Default, Base32Alphabet.Default, padding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromSpan(ReadOnlySpan value, Encoding encoding, bool padding) - { - return FromSpan(value, encoding, Base32Alphabet.Default, padding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromSpan(ReadOnlySpan value, Base32Alphabet alphabet) - { - return FromSpan(value, Encoding.Default, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromSpan(ReadOnlySpan value, Encoding encoding, Base32Alphabet alphabet) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromSpan(ReadOnlySpan value, Base32Alphabet alphabet, bool padding) - { - return FromSpan(value, Encoding.Default, alphabet, padding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromSpan(ReadOnlySpan value, Encoding encoding, Base32Alphabet alphabet, - bool padding) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding, alphabet, padding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Returns a new instance. - public static Base32 FromString(string value) - { - return FromString(value, Encoding.Default, Base32Alphabet.Default, true); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base32 FromString(string value, Encoding encoding) - { - return FromString(value, encoding, Base32Alphabet.Default, true); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromString(string value, bool padding) - { - return FromString(value, Encoding.Default, Base32Alphabet.Default, padding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromString(string value, Encoding encoding, bool padding) - { - return FromString(value, encoding, Base32Alphabet.Default, padding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromString(string value, Base32Alphabet alphabet) - { - return FromString(value, Encoding.Default, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromString(string value, Encoding encoding, Base32Alphabet alphabet) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromString(string value, Base32Alphabet alphabet, bool padding) - { - return FromString(value, Encoding.Default, alphabet, padding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 FromString(string value, Encoding encoding, Base32Alphabet alphabet, bool padding) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding, alphabet, padding); - } -} diff --git a/OnixLabs.Core/Text/Base32.Parse.cs b/OnixLabs.Core/Text/Base32.Parse.cs index 0b81a7a..32c47d3 100644 --- a/OnixLabs.Core/Text/Base32.Parse.cs +++ b/OnixLabs.Core/Text/Base32.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,51 +22,7 @@ public readonly partial struct Base32 /// Parses a Base-32 value into a instance. /// /// The Base-16 (hexadecimal) value to parse. - /// A new instance. - public static Base32 Parse(string value) - { - return Parse(value, Base32Alphabet.Default); - } - - /// - /// Parses a Base-32 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// A new instance. - public static Base32 Parse(string value, Base32Alphabet alphabet) - { - ReadOnlySpan characters = value.AsSpan(); - return Parse(characters, alphabet); - } - - /// - /// Parses a Base-32 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// A new instance. - public static Base32 Parse(char[] value) - { - return Parse(value, Base32Alphabet.Default); - } - - /// - /// Parses a Base-32 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// A new instance. - public static Base32 Parse(char[] value, Base32Alphabet alphabet) - { - ReadOnlySpan characters = value.AsSpan(); - return Parse(characters, alphabet); - } - - /// - /// Parses a Base-32 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// A new instance. + /// Returns a new instance. public static Base32 Parse(ReadOnlySpan value) { return Parse(value, Base32Alphabet.Default); @@ -77,11 +33,11 @@ public static Base32 Parse(ReadOnlySpan value) /// /// The Base-16 (hexadecimal) value to parse. /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// A new instance. + /// Returns a new instance. public static Base32 Parse(ReadOnlySpan value, Base32Alphabet alphabet) { bool padding = value.Contains('='); byte[] bytes = Decode(value, alphabet.Alphabet, padding); - return FromByteArray(bytes, padding); + return Create(bytes, padding); } } diff --git a/OnixLabs.Core/Text/Base32.To.cs b/OnixLabs.Core/Text/Base32.To.cs index eded14e..25a7ee4 100644 --- a/OnixLabs.Core/Text/Base32.To.cs +++ b/OnixLabs.Core/Text/Base32.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.cs b/OnixLabs.Core/Text/Base32.cs index 855b754..d26150f 100644 --- a/OnixLabs.Core/Text/Base32.cs +++ b/OnixLabs.Core/Text/Base32.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ namespace OnixLabs.Core.Text; /// /// Represents a Base-32 value. /// -public readonly partial struct Base32 +public readonly partial struct Base32 : IBase { /// /// Initializes a new instance of the struct. @@ -27,7 +27,7 @@ public readonly partial struct Base32 /// Determines whether padding should be applied for Base-32 encoding and decoding operations. private Base32(byte[] value, Base32Alphabet alphabet, bool padding) { - Value = value; + Value = value.Copy(); Alphabet = alphabet; Padding = padding; } diff --git a/OnixLabs.Core/Text/Base32Alphabet.cs b/OnixLabs.Core/Text/Base32Alphabet.cs index b27ca52..07bc9b6 100644 --- a/OnixLabs.Core/Text/Base32Alphabet.cs +++ b/OnixLabs.Core/Text/Base32Alphabet.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,32 +22,27 @@ public sealed class Base32Alphabet : Enumeration /// /// The default (RFC-4648) Base-32 alphabet. /// - public static readonly Base32Alphabet Default = - new(0, nameof(Default), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); + public static Base32Alphabet Default => new(0, nameof(Default), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); /// /// The Z-Base-32 alphabet. /// - public static readonly Base32Alphabet ZBase32 = - new(1, nameof(ZBase32), "ybndrfg8ejkmcpqxot1uwisza345h769"); + public static Base32Alphabet ZBase32 => new(1, nameof(ZBase32), "ybndrfg8ejkmcpqxot1uwisza345h769"); /// /// The Geohash Base-32 alphabet. /// - public static readonly Base32Alphabet GeoHash = - new(2, nameof(GeoHash), "0123456789bcdefghjkmnpqrstuvwxyz"); + public static Base32Alphabet GeoHash => new(2, nameof(GeoHash), "0123456789bcdefghjkmnpqrstuvwxyz"); /// /// The Crockford Base-32 alphabet. /// - public static readonly Base32Alphabet Crockford = - new(3, nameof(Crockford), "0123456789ABCDEFGHJKMNPQRSTVWXYZ"); + public static Base32Alphabet Crockford => new(3, nameof(Crockford), "0123456789ABCDEFGHJKMNPQRSTVWXYZ"); /// /// The Base-32 Hex alphabet. /// - public static readonly Base32Alphabet Base32Hex = - new(4, nameof(Base32Hex), "0123456789ABCDEFGHIJKLMNOPQRSTUV"); + public static Base32Alphabet Base32Hex => new(4, nameof(Base32Hex), "0123456789ABCDEFGHIJKLMNOPQRSTUV"); /// /// Initializes a new instance of the class. diff --git a/OnixLabs.Core/Text/Base58.Checksum.cs b/OnixLabs.Core/Text/Base58.Checksum.cs index 9222d17..9962a13 100644 --- a/OnixLabs.Core/Text/Base58.Checksum.cs +++ b/OnixLabs.Core/Text/Base58.Checksum.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.Codec.cs b/OnixLabs.Core/Text/Base58.Codec.cs index 36b1146..f3fe9a7 100644 --- a/OnixLabs.Core/Text/Base58.Codec.cs +++ b/OnixLabs.Core/Text/Base58.Codec.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ private static string Encode(byte[] value, string alphabet) { BigInteger remainder = data % 58; data /= 58; - result.Insert(0, alphabet[(int) remainder]); + result.Insert(0, alphabet[(int)remainder]); } for (int index = 0; index < value.Length && value[index] == 0; index++) diff --git a/OnixLabs.Core/Text/Base58.Empty.cs b/OnixLabs.Core/Text/Base58.Constants.cs similarity index 68% rename from OnixLabs.Core/Text/Base58.Empty.cs rename to OnixLabs.Core/Text/Base58.Constants.cs index e6674c0..ded5b32 100644 --- a/OnixLabs.Core/Text/Base58.Empty.cs +++ b/OnixLabs.Core/Text/Base58.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,22 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; +using OnixLabs.Core.Collections; namespace OnixLabs.Core.Text; public readonly partial struct Base58 { /// - /// Gets an empty Base-58 value. + /// Gets an empty value. /// - public static readonly Base58 Empty; - - /// - /// Initializes static members of the class. - /// - static Base58() - { - Empty = FromByteArray(Array.Empty()); - } + public static Base58 Empty => Create(Collection.EmptyArray()); } diff --git a/OnixLabs.Core/Text/Base58.Create.cs b/OnixLabs.Core/Text/Base58.Create.cs new file mode 100644 index 0000000..1e28dd3 --- /dev/null +++ b/OnixLabs.Core/Text/Base58.Create.cs @@ -0,0 +1,88 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Text; + +namespace OnixLabs.Core.Text; + +public readonly partial struct Base58 +{ + /// + /// Creates a instance from the specified array. + /// + /// The underlying value. + /// Returns a new instance. + public static Base58 Create(byte[] value) + { + return Create(value, Base58Alphabet.Default); + } + + /// + /// Creates a instance from the specified array. + /// + /// The underlying value. + /// The alphabet that will be used for Base-58 encoding and decoding operations. + /// Returns a new instance. + public static Base58 Create(byte[] value, Base58Alphabet alphabet) + { + return new Base58(value, alphabet); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// Returns a new instance. + public static Base58 Create(ReadOnlySpan value) + { + return Create(value, Encoding.Default, Base58Alphabet.Default); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The encoding to use to obtain the underlying value. + /// Returns a new instance. + public static Base58 Create(ReadOnlySpan value, Encoding encoding) + { + return Create(value, encoding, Base58Alphabet.Default); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The alphabet that will be used for Base-58 encoding and decoding operations. + /// Returns a new instance. + public static Base58 Create(ReadOnlySpan value, Base58Alphabet alphabet) + { + return Create(value, Encoding.Default, alphabet); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The encoding to use to obtain the underlying value. + /// The alphabet that will be used for Base-58 encoding and decoding operations. + /// Returns a new instance. + public static Base58 Create(ReadOnlySpan value, Encoding encoding, Base58Alphabet alphabet) + { + // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. + byte[] bytes = encoding.GetBytes(value.ToArray()); + return Create(bytes, alphabet); + } +} diff --git a/OnixLabs.Core/Text/Base58.Equatable.cs b/OnixLabs.Core/Text/Base58.Equatable.cs index d310372..b01f2b8 100644 --- a/OnixLabs.Core/Text/Base58.Equatable.cs +++ b/OnixLabs.Core/Text/Base58.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,56 +18,56 @@ namespace OnixLabs.Core.Text; -public readonly partial struct Base58 : IEquatable +public readonly partial struct Base58 { /// - /// Performs an equality check between two object instances. + /// Checks for equality between the current instance and another object. /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(Base58 a, Base58 b) + /// The object to check for equality. + /// Returns true if the object is equal to the current instance; otherwise, false. + public bool Equals(Base58 other) { - return Equals(a, b); + return other.Value.SequenceEqual(Value) && other.Alphabet == Alphabet; } /// - /// Performs an inequality check between two object instances. + /// Checks for equality between the current instance and another object. /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(Base58 a, Base58 b) + /// The object to check for equality. + /// Returns true if the object is equal to the current instance; otherwise, false. + public override bool Equals(object? obj) { - return !Equals(a, b); + return obj is Base58 other && Equals(other); } /// - /// Checks for equality between this instance and another object. + /// Serves as a hash code function for the current instance. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public bool Equals(Base58 other) + /// Returns a hash code for the current instance. + public override int GetHashCode() { - return other.Value.SequenceEqual(Value) && other.Alphabet == Alphabet; + return HashCode.Combine(Value.GetContentHashCode()); } /// - /// Checks for equality between this instance and another object. + /// Performs an equality check between two object instances. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public override bool Equals(object? obj) + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns true if the instances are equal; otherwise, false. + public static bool operator ==(Base58 left, Base58 right) { - return obj is Base58 other && Equals(other); + return Equals(left, right); } /// - /// Serves as a hash code function for this instance. + /// Performs an inequality check between two object instances. /// - /// A hash code for this instance. - public override int GetHashCode() + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns true if the instances are not equal; otherwise, false. + public static bool operator !=(Base58 left, Base58 right) { - return HashCode.Combine(Value.GetContentHashCode()); + return !Equals(left, right); } } diff --git a/OnixLabs.Core/Text/Base58.From.cs b/OnixLabs.Core/Text/Base58.From.cs deleted file mode 100644 index 807c59f..0000000 --- a/OnixLabs.Core/Text/Base58.From.cs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2020-2022 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base58 -{ - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Returns a new instance. - public static Base58 FromByteArray(byte[] value) - { - return new Base58(value, Base58Alphabet.Default); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 FromByteArray(byte[] value, Base58Alphabet alphabet) - { - return new Base58(value, alphabet); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Returns a new instance. - public static Base58 FromCharArray(char[] value) - { - return FromCharArray(value, Encoding.Default, Base58Alphabet.Default); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base58 FromCharArray(char[] value, Encoding encoding) - { - return FromCharArray(value, encoding, Base58Alphabet.Default); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 FromCharArray(char[] value, Base58Alphabet alphabet) - { - return FromCharArray(value, Encoding.Default, alphabet); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 FromCharArray(char[] value, Encoding encoding, Base58Alphabet alphabet) - { - byte[] bytes = encoding.GetBytes(value); - return FromByteArray(bytes, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Returns a new instance. - public static Base58 FromSpan(ReadOnlySpan value) - { - return FromSpan(value, Encoding.Default, Base58Alphabet.Default); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base58 FromSpan(ReadOnlySpan value, Encoding encoding) - { - return FromSpan(value, encoding, Base58Alphabet.Default); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 FromSpan(ReadOnlySpan value, Base58Alphabet alphabet) - { - return FromSpan(value, Encoding.Default, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 FromSpan(ReadOnlySpan value, Encoding encoding, Base58Alphabet alphabet) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Returns a new instance. - public static Base58 FromString(string value) - { - return FromString(value, Encoding.Default, Base58Alphabet.Default); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base58 FromString(string value, Encoding encoding) - { - return FromString(value, encoding, Base58Alphabet.Default); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 FromString(string value, Base58Alphabet alphabet) - { - return FromString(value, Encoding.Default, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 FromString(string value, Encoding encoding, Base58Alphabet alphabet) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding, alphabet); - } -} diff --git a/OnixLabs.Core/Text/Base58.Parse.cs b/OnixLabs.Core/Text/Base58.Parse.cs index ef75b70..6cbb20d 100644 --- a/OnixLabs.Core/Text/Base58.Parse.cs +++ b/OnixLabs.Core/Text/Base58.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,51 +22,7 @@ public readonly partial struct Base58 /// Parses a Base-58 value into a instance. /// /// The Base-16 (hexadecimal) value to parse. - /// A new instance. - public static Base58 Parse(string value) - { - return Parse(value, Base58Alphabet.Default); - } - - /// - /// Parses a Base-58 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// A new instance. - public static Base58 Parse(string value, Base58Alphabet alphabet) - { - ReadOnlySpan characters = value.AsSpan(); - return Parse(characters, alphabet); - } - - /// - /// Parses a Base-58 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// A new instance. - public static Base58 Parse(char[] value) - { - return Parse(value, Base58Alphabet.Default); - } - - /// - /// Parses a Base-58 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// A new instance. - public static Base58 Parse(char[] value, Base58Alphabet alphabet) - { - ReadOnlySpan characters = value.AsSpan(); - return Parse(characters, alphabet); - } - - /// - /// Parses a Base-58 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// A new instance. + /// Returns a new instance. public static Base58 Parse(ReadOnlySpan value) { return Parse(value, Base58Alphabet.Default); @@ -77,55 +33,11 @@ public static Base58 Parse(ReadOnlySpan value) /// /// The Base-16 (hexadecimal) value to parse. /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// A new instance. + /// Returns a new instance. public static Base58 Parse(ReadOnlySpan value, Base58Alphabet alphabet) { byte[] bytes = Decode(value, alphabet.Alphabet); - return FromByteArray(bytes, alphabet); - } - - /// - /// Parses a Base-58 value with a checksum into a instance. - /// - /// The Base-16 (hexadecimal) value to ParseWithChecksum. - /// A new instance. - public static Base58 ParseWithChecksum(string value) - { - return ParseWithChecksum(value, Base58Alphabet.Default); - } - - /// - /// Parses a Base-58 value with a checksum into a instance. - /// - /// The Base-16 (hexadecimal) value to ParseWithChecksum. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// A new instance. - public static Base58 ParseWithChecksum(string value, Base58Alphabet alphabet) - { - ReadOnlySpan characters = value.AsSpan(); - return ParseWithChecksum(characters, alphabet); - } - - /// - /// Parses a Base-58 value with a checksum into a instance. - /// - /// The Base-16 (hexadecimal) value to ParseWithChecksum. - /// A new instance. - public static Base58 ParseWithChecksum(char[] value) - { - return ParseWithChecksum(value, Base58Alphabet.Default); - } - - /// - /// Parses a Base-58 value with a checksum into a instance. - /// - /// The Base-16 (hexadecimal) value to ParseWithChecksum. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// A new instance. - public static Base58 ParseWithChecksum(char[] value, Base58Alphabet alphabet) - { - ReadOnlySpan characters = value.AsSpan(); - return ParseWithChecksum(characters, alphabet); + return Create(bytes, alphabet); } /// @@ -151,6 +63,6 @@ public static Base58 ParseWithChecksum(ReadOnlySpan value, Base58Alphabet VerifyChecksum(bytes); - return FromByteArray(bytesWithoutChecksum, alphabet); + return Create(bytesWithoutChecksum, alphabet); } } diff --git a/OnixLabs.Core/Text/Base58.To.cs b/OnixLabs.Core/Text/Base58.To.cs index 767e2f8..c175678 100644 --- a/OnixLabs.Core/Text/Base58.To.cs +++ b/OnixLabs.Core/Text/Base58.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ public byte[] ToByteArray() /// /// Returns a that represents the current object, with a checksum. /// - /// A that represents the current object, with a checksum. + /// Returns a that represents the current object, with a checksum. public string ToStringWithChecksum() { byte[] valueWithChecksum = AddChecksum(Value); diff --git a/OnixLabs.Core/Text/Base58.cs b/OnixLabs.Core/Text/Base58.cs index 178bcae..6601b04 100644 --- a/OnixLabs.Core/Text/Base58.cs +++ b/OnixLabs.Core/Text/Base58.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ namespace OnixLabs.Core.Text; /// /// Represents a Base-58 value. /// -public readonly partial struct Base58 +public readonly partial struct Base58 : IBase { /// /// Initializes a new instance of the struct. @@ -26,7 +26,7 @@ public readonly partial struct Base58 /// The alphabet that will be used for Base-58 encoding and decoding operations. private Base58(byte[] value, Base58Alphabet alphabet) { - Value = value; + Value = value.Copy(); Alphabet = alphabet; } diff --git a/OnixLabs.Core/Text/Base58Alphabet.cs b/OnixLabs.Core/Text/Base58Alphabet.cs index 6cde86c..e0b608e 100644 --- a/OnixLabs.Core/Text/Base58Alphabet.cs +++ b/OnixLabs.Core/Text/Base58Alphabet.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,20 +22,17 @@ public sealed class Base58Alphabet : Enumeration /// /// The default Base-58 alphabet, which is the same as Bitcoin's Base-58 alphabet. /// - public static readonly Base58Alphabet Default = - new(0, nameof(Default), "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"); + public static Base58Alphabet Default => new(0, nameof(Default), "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"); /// /// The Ripple Base-58 alphabet. /// - public static readonly Base58Alphabet Ripple = - new(0, nameof(Ripple), "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"); + public static Base58Alphabet Ripple => new(0, nameof(Ripple), "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"); /// /// The Flickr Base-58 alphabet. /// - public static readonly Base58Alphabet Flickr = - new(0, nameof(Flickr), "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"); + public static Base58Alphabet Flickr => new(0, nameof(Flickr), "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"); /// /// Initializes a new instance of the class. diff --git a/OnixLabs.Core/Text/Base64.Empty.cs b/OnixLabs.Core/Text/Base64.Constants.cs similarity index 68% rename from OnixLabs.Core/Text/Base64.Empty.cs rename to OnixLabs.Core/Text/Base64.Constants.cs index 53a24fa..42f665a 100644 --- a/OnixLabs.Core/Text/Base64.Empty.cs +++ b/OnixLabs.Core/Text/Base64.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,22 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; +using OnixLabs.Core.Collections; namespace OnixLabs.Core.Text; public readonly partial struct Base64 { /// - /// Gets an empty Base-64 value. + /// Gets an empty value. /// - public static readonly Base64 Empty; - - /// - /// Initializes static members of the class. - /// - static Base64() - { - Empty = FromByteArray(Array.Empty()); - } + public static Base64 Empty => Create(Collection.EmptyArray()); } diff --git a/OnixLabs.Core/Text/Base64.Create.cs b/OnixLabs.Core/Text/Base64.Create.cs new file mode 100644 index 0000000..cc1e893 --- /dev/null +++ b/OnixLabs.Core/Text/Base64.Create.cs @@ -0,0 +1,54 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Text; + +namespace OnixLabs.Core.Text; + +public readonly partial struct Base64 +{ + /// + /// Creates a instance from the specified array. + /// + /// The underlying value. + /// Returns a new instance. + public static Base64 Create(byte[] value) + { + return new Base64(value); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// Returns a new instance. + public static Base64 Create(ReadOnlySpan value) + { + return Create(value, Encoding.Default); + } + + /// + /// Creates a instance from the specified . + /// + /// The underlying value. + /// The encoding to use to obtain the underlying value. + /// Returns a new instance. + public static Base64 Create(ReadOnlySpan value, Encoding encoding) + { + // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. + byte[] bytes = encoding.GetBytes(value.ToArray()); + return Create(bytes); + } +} diff --git a/OnixLabs.Core/Text/Base64.Equatable.cs b/OnixLabs.Core/Text/Base64.Equatable.cs index a039f08..c20dd40 100644 --- a/OnixLabs.Core/Text/Base64.Equatable.cs +++ b/OnixLabs.Core/Text/Base64.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,56 +18,56 @@ namespace OnixLabs.Core.Text; -public readonly partial struct Base64 : IEquatable +public readonly partial struct Base64 { /// - /// Performs an equality check between two object instances. + /// Checks for equality between the current instance and another object. /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(Base64 a, Base64 b) + /// The object to check for equality. + /// Returns true if the object is equal to the current instance; otherwise, false. + public bool Equals(Base64 other) { - return Equals(a, b); + return other.Value.SequenceEqual(Value); } /// - /// Performs an inequality check between two object instances. + /// Checks for equality between the current instance and another object. /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(Base64 a, Base64 b) + /// The object to check for equality. + /// Returns true if the object is equal to the current instance; otherwise, false. + public override bool Equals(object? obj) { - return !Equals(a, b); + return obj is Base64 other && Equals(other); } /// - /// Checks for equality between this instance and another object. + /// Serves as a hash code function for the current instance. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public bool Equals(Base64 other) + /// Returns a hash code for the current instance. + public override int GetHashCode() { - return other.Value.SequenceEqual(Value); + return HashCode.Combine(Value.GetContentHashCode()); } /// - /// Checks for equality between this instance and another object. + /// Performs an equality check between two object instances. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public override bool Equals(object? obj) + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(Base64 left, Base64 right) { - return obj is Base64 other && Equals(other); + return Equals(left, right); } /// - /// Serves as a hash code function for this instance. + /// Performs an inequality check between two object instances. /// - /// A hash code for this instance. - public override int GetHashCode() + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(Base64 left, Base64 right) { - return HashCode.Combine(Value.GetContentHashCode()); + return !Equals(left, right); } } diff --git a/OnixLabs.Core/Text/Base64.From.cs b/OnixLabs.Core/Text/Base64.From.cs deleted file mode 100644 index f2fe891..0000000 --- a/OnixLabs.Core/Text/Base64.From.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2020-2022 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base64 -{ - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Returns a new instance. - public static Base64 FromByteArray(byte[] value) - { - return new Base64(value); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// Returns a new instance. - public static Base64 FromCharArray(char[] value) - { - return FromCharArray(value, Encoding.Default); - } - - /// - /// Creates a instance from the specified array. - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base64 FromCharArray(char[] value, Encoding encoding) - { - byte[] bytes = encoding.GetBytes(value); - return FromByteArray(bytes); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Returns a new instance. - public static Base64 FromSpan(ReadOnlySpan value) - { - return FromSpan(value, Encoding.Default); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base64 FromSpan(ReadOnlySpan value, Encoding encoding) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Returns a new instance. - public static Base64 FromString(string value) - { - return FromString(value, Encoding.Default); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base64 FromString(string value, Encoding encoding) - { - char[] characters = value.ToArray(); - return FromCharArray(characters, encoding); - } -} diff --git a/OnixLabs.Core/Text/Base64.Parse.cs b/OnixLabs.Core/Text/Base64.Parse.cs index 89292d3..30d5656 100644 --- a/OnixLabs.Core/Text/Base64.Parse.cs +++ b/OnixLabs.Core/Text/Base64.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,28 +18,6 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base64 { - /// - /// Parses a Base-64 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// Returns a new instance. - public static Base64 Parse(string value) - { - char[] characters = value.ToCharArray(); - return Parse(characters); - } - - /// - /// Parses a Base-64 value into a instance. - /// - /// The Base-16 (hexadecimal) value to parse. - /// Returns a new instance. - public static Base64 Parse(char[] value) - { - byte[] bytes = Convert.FromBase64CharArray(value, 0, value.Length); - return FromByteArray(bytes); - } - /// /// Parses a Base-64 value into a instance. /// @@ -47,7 +25,7 @@ public static Base64 Parse(char[] value) /// Returns a new instance. public static Base64 Parse(ReadOnlySpan value) { - char[] characters = value.ToArray(); - return Parse(characters); + byte[] bytes = Convert.FromBase64String(value.ToString()); + return Create(bytes); } } diff --git a/OnixLabs.Core/Text/Base64.To.cs b/OnixLabs.Core/Text/Base64.To.cs index faea21b..b1bf57c 100644 --- a/OnixLabs.Core/Text/Base64.To.cs +++ b/OnixLabs.Core/Text/Base64.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -50,7 +50,7 @@ public string ToPlainTextString(Encoding encoding) /// /// Returns a that represents the current object. /// - /// A that represents the current object. + /// Returns a that represents the current object. public override string ToString() { return Convert.ToBase64String(Value); diff --git a/OnixLabs.Core/Text/Base64.cs b/OnixLabs.Core/Text/Base64.cs index 0894e33..bb44ee5 100644 --- a/OnixLabs.Core/Text/Base64.cs +++ b/OnixLabs.Core/Text/Base64.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ namespace OnixLabs.Core.Text; /// /// Represents a Base-64 value. /// -public readonly partial struct Base64 +public readonly partial struct Base64 : IBase { /// /// Initializes a new instance of the struct. @@ -25,7 +25,7 @@ public readonly partial struct Base64 /// The underlying value. private Base64(byte[] value) { - Value = value; + Value = value.Copy(); } /// diff --git a/OnixLabs.Core/Text/IBase.cs b/OnixLabs.Core/Text/IBase.cs new file mode 100644 index 0000000..942607d --- /dev/null +++ b/OnixLabs.Core/Text/IBase.cs @@ -0,0 +1,93 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Text; + +namespace OnixLabs.Core.Text; + +/// +/// Represents a number base representation. +/// +/// The underlying type of the number base representation. +public interface IBase : IEquatable where TSelf : struct, IBase +{ + /// + /// Gets an empty value. + /// + public static virtual TSelf Empty => TSelf.Create(EmptyArray()); + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(byte[] value); + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static virtual TSelf Create(ReadOnlySpan value) + { + return TSelf.Create(value, Encoding.Default); + } + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The from which to obtain a value. + /// Returns a new value from the specified value. + public static virtual TSelf Create(ReadOnlySpan value, Encoding encoding) + { + // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. + byte[] bytes = encoding.GetBytes(value.ToArray()); + return TSelf.Create(bytes); + } + + /// + /// Parses a value from the specified value. + /// + /// The value from which to parse a value. + /// Returns a new value parsed from the specified value. + public static abstract TSelf Parse(ReadOnlySpan value); + + /// + /// Gets the current as a value. + /// + /// Returns the current as a value. + byte[] ToByteArray(); + + /// + /// Gets the plain-text representation of the current value. + /// + /// Returns the plain-text representation of the current value. + public string ToPlainTextString() + { + return ToPlainTextString(Encoding.Default); + } + + /// + /// Gets the plain-text representation of the current value. + /// + /// The from which to obtain a value. + /// Returns the plain-text representation of the current value. + public string ToPlainTextString(Encoding encoding) + { + byte[] bytes = ToByteArray(); + return encoding.GetString(bytes); + } +} diff --git a/OnixLabs.Playground/OnixLabs.Playground.csproj b/OnixLabs.Playground/OnixLabs.Playground.csproj index a5c1a76..faf427b 100644 --- a/OnixLabs.Playground/OnixLabs.Playground.csproj +++ b/OnixLabs.Playground/OnixLabs.Playground.csproj @@ -2,14 +2,16 @@ Exe - net6.0 + net7.0 enable - 10 + 11 - - + + + + diff --git a/OnixLabs.Playground/Program.cs b/OnixLabs.Playground/Program.cs index c7964e3..6928888 100644 --- a/OnixLabs.Playground/Program.cs +++ b/OnixLabs.Playground/Program.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs b/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs new file mode 100644 index 0000000..8910d38 --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs @@ -0,0 +1,63 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography.UnitTests.Data.Objects; + +public sealed class MerkleNode : IEquatable, IHashable +{ + public MerkleNode(string text, int number, DateTime moment, Guid identifier) + { + Text = text; + Number = number; + Moment = moment; + Identifier = identifier; + } + + public string Text { get; } + public int Number { get; } + public DateTime Moment { get; } + public Guid Identifier { get; } + + public Hash ComputeHash() + { + return Hash.ComputeSha2Hash256(ToString()); + } + + public bool Equals(MerkleNode? other) + { + return ReferenceEquals(this, other) + || other is not null + && other.Text == Text + && other.Number == Number + && other.Moment == Moment + && other.Identifier == Identifier; + } + + public override bool Equals(object? obj) + { + return Equals(obj as MerkleNode); + } + + public override int GetHashCode() + { + return HashCode.Combine(Text, Number, Moment, Identifier); + } + + public override string ToString() + { + return this.ToRecordString(); + } +} diff --git a/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj b/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj new file mode 100644 index 0000000..8096231 --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj @@ -0,0 +1,32 @@ + + + + net7.0 + enable + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs index 12ffbbc..51ab09c 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs index 72cb3e1..df56126 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs index dfdbcea..b0af0f8 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ public void TwoIdenticalPrivateKeysShouldBeConsideredEqual() // Act Base58 base58PrivateKey = privateKey1.ToBase58(); - PrivateKey privateKey2 = EcdsaPrivateKey.FromBase58(base58PrivateKey, type); + PrivateKey privateKey2 = EcdsaPrivateKey.Create(base58PrivateKey, type); // Assert Assert.Equal(privateKey1, privateKey2); @@ -46,7 +46,7 @@ public void TwoIdenticalPublicKeysShouldBeConsideredEqual() // Act Base58 base58PublicKey = publicKey1.ToBase58(); - PublicKey publicKey2 = EcdsaPublicKey.FromBase58(base58PublicKey, type); + PublicKey publicKey2 = EcdsaPublicKey.Create(base58PublicKey, type); // Assert Assert.Equal(publicKey1, publicKey2); @@ -60,7 +60,7 @@ public void TwoIdenticalEcdsaKeysShouldBeAbleToSignAndVerifyTheSameData() HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = EcdsaPrivateKey.FromBase64(privateKey1.ToBase64(), type); + PrivateKey privateKey2 = EcdsaPrivateKey.Create(privateKey1.ToBase64(), type); PublicKey publicKey1 = pair.PublicKey; PublicKey publicKey2 = privateKey1.GetPublicKey(); @@ -91,7 +91,7 @@ public void TwoIdenticalEcdsaKeysShouldBeAbleToSignAndVerifyTheSameHash() HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = EcdsaPrivateKey.FromBase64(privateKey1.ToBase64(), type); + PrivateKey privateKey2 = EcdsaPrivateKey.Create(privateKey1.ToBase64(), type); PublicKey publicKey1 = pair.PublicKey; PublicKey publicKey2 = privateKey1.GetPublicKey(); diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs index ffba6fc..2727b78 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs index 240c376..458a36e 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core.Collections; using Xunit; namespace OnixLabs.Security.Cryptography.UnitTests; @@ -55,6 +56,51 @@ public void DifferentHashesShouldNotBeConsideredEqual() Assert.NotEqual(a, b); } + [Fact(DisplayName = "Hashes should produce a negative-one sort order when the left-hand hash is less than the right-hand hash")] + public void HashesShouldProduceANegativeOneSortOrderWhenTheLeftHandHashIsLessThanTheRightHandHash() + { + // Arrange + Hash a = Hash.Create(Collection.ArrayOf(1)); + Hash b = Hash.Create(Collection.ArrayOf(2)); + const int expected = -1; + + // Act + int actual = a.CompareTo(b); + + // Assert + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Hashes should produce a positive-one sort order when the left-hand hash is greater than the right-hand hash")] + public void HashesShouldProduceAPositiveOneSortOrderWhenTheLeftHandHashIsGreaterThanTheRightHandHash() + { + // Arrange + Hash a = Hash.Create(Collection.ArrayOf(2)); + Hash b = Hash.Create(Collection.ArrayOf(1)); + const int expected = 1; + + // Act + int actual = a.CompareTo(b); + + // Assert + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Hashes should produce a zero sort order when the left-hand hash is equal to the right-hand hash")] + public void HashesShouldProduceAZeroSortOrderWhenTheLeftHandHashIsEqualToTheRightHandHash() + { + // Arrange + Hash a = Hash.Create(Collection.ArrayOf(1)); + Hash b = Hash.Create(Collection.ArrayOf(1)); + const int expected = 0; + + // Act + int actual = a.CompareTo(b); + + // Assert + Assert.Equal(expected, actual); + } + [Fact(DisplayName = "Parse should be able to parse a known hash")] public void ParseShouldBeAbleToParseAKnownHash() { diff --git a/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs index 12d7382..289f306 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs index eea32c7..98206c4 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs index 095071b..0fec088 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs new file mode 100644 index 0000000..2fab50a --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs @@ -0,0 +1,106 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Linq; +using OnixLabs.Core; +using OnixLabs.Core.Collections; +using OnixLabs.Security.Cryptography.UnitTests.Data.Objects; +using Xunit; + +namespace OnixLabs.Security.Cryptography.UnitTests; + +public sealed class MerkleTreeGenericTests +{ + private readonly IEnumerable setA = Collection.EnumerableOf( + new MerkleNode("abc", 123, "1953-05-08T01:00:59Z".ToDateTime(), Guid.Parse("18d1e14c-9762-4b2c-8774-3f053e8579e0")), + new MerkleNode("def", 456, "1953-05-08T06:30:00Z".ToDateTime(), Guid.Parse("a5d0ad36-f9a6-4fb0-9374-aa658eb19a51")), + new MerkleNode("hij", 789, "1953-05-08T12:00:33Z".ToDateTime(), Guid.Parse("0d324d48-d451-416e-ac4d-fed1a324d446")), + new MerkleNode("klm", 101, "1953-05-08T18:30:00Z".ToDateTime(), Guid.Parse("dc2bb378-114e-4f5d-8674-92729a67fe3d")), + new MerkleNode("nop", 112, "1953-05-08T23:00:59Z".ToDateTime(), Guid.Parse("193863c7-3bfa-4a3c-874a-a99d98b38358")) + ); + + private readonly IEnumerable setB = Collection.EnumerableOf( + new MerkleNode("qrs", 123, "1900-05-08T01:00:59Z".ToDateTime(), Guid.Parse("893576c9-7cb1-4653-a7c4-21e5ba9e7275")), + new MerkleNode("tuv", 456, "1901-05-08T06:30:00Z".ToDateTime(), Guid.Parse("e7543a7e-3a52-48f5-842e-9448931f1cde")), + new MerkleNode("qxy", 789, "1902-05-08T12:00:33Z".ToDateTime(), Guid.Parse("d228ab75-d36a-4392-9c51-888a5b7f9db7")), + new MerkleNode("zab", 101, "1903-05-08T18:30:00Z".ToDateTime(), Guid.Parse("f73180c0-1fc8-4492-ae5d-f0b8962177a8")) + ); + + [Fact(DisplayName = "Identical Merkle trees should be considered equal")] + public void IdenticalMerkleTreesShouldBeConsideredEqual() + { + // Arrange / Act + MerkleTree a = MerkleTree.Create(setA); + MerkleTree b = MerkleTree.Create(setA); + + // Assert + Assert.Equal(a, b); + Assert.Equal(a.Hash, b.Hash); + } + + [Fact(DisplayName = "Different Merkle trees should not be considered equal")] + public void DifferentMerkleTreesShouldNotBeConsideredEqual() + { + // Arrange / Act + MerkleTree a = MerkleTree.Create(setA); + MerkleTree b = MerkleTree.Create(setB); + + // Assert + Assert.NotEqual(a, b); + Assert.NotEqual(a.Hash, b.Hash); + } + + [Fact(DisplayName = "MerkleTree.GetLeafHashes should produce the same leaf hashes that the tree was constructed with")] + public void MerkleTreeGetLeafHashesShouldProduceTheSameLeafHashesThatTheTreeWasConstructedWith() + { + // Arrange + IEnumerable expected = setA.Select(value => value.ComputeHash()); + MerkleTree candidate = MerkleTree.Create(setA); + + // Act + IEnumerable actual = candidate.GetLeafHashes(); + + // Assert + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "MerkleTree.GetLeafValues should produce the same leaf values that the tree was constructed with")] + public void MerkleTreeGetLeafValuesShouldProduceTheSameLeafValuesThatTheTreeWasConstructedWith() + { + // Arrange + MerkleTree candidate = MerkleTree.Create(setA); + + // Act + IEnumerable actual = candidate.GetLeafValues(); + + // Assert + Assert.Equal(setA, actual); + } + + [Fact(DisplayName = "MerkleTree.ToMerkleTree should produce a hash-only, non-generic Merkle tree that is equal in value")] + public void MerkleTreeToMerkleTreeShouldProduceAHashOnlyNonGenericMerkleTreeThatIsEqualInValue() + { + // Arrange + MerkleTree a = MerkleTree.Create(setA); + + // Act + MerkleTree b = a.ToMerkleTree(); + + // Assert + Assert.Equal(a, b); + Assert.Equal(a.Hash, b.Hash); + } +} diff --git a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs index 524645d..e62d418 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,42 +20,61 @@ namespace OnixLabs.Security.Cryptography.UnitTests; public sealed class MerkleTreeTests { + private readonly IEnumerable setA = Enumerable.Range(123, 1357).Select(i => Hash.ComputeSha2Hash256($"A{i}")).ToList(); + private readonly IEnumerable setB = Enumerable.Range(100, 1000).Select(i => Hash.ComputeSha2Hash256($"B{i}")).ToList(); + [Fact(DisplayName = "Identical Merkle trees should be considered equal")] public void IdenticalMerkleTreesShouldBeConsideredEqual() { - // Arrange - List hashes = Enumerable - .Range(1, 937) - .Select(i => Hash.ComputeSha2Hash256(i.ToString())) - .ToList(); - - // Act - MerkleTree a = MerkleTree.Build(hashes); - MerkleTree b = MerkleTree.Build(hashes); + // Arrange / Act + MerkleTree a = MerkleTree.Create(setA); + MerkleTree b = MerkleTree.Create(setA); // Assert Assert.Equal(a, b); + Assert.Equal(a.Hash, b.Hash); } [Fact(DisplayName = "Different Merkle trees should not be considered equal")] public void DifferentMerkleTreesShouldNotBeConsideredEqual() + { + // Arrange / Act + MerkleTree a = MerkleTree.Create(setA); + MerkleTree b = MerkleTree.Create(setB); + + // Assert + Assert.NotEqual(a, b); + Assert.NotEqual(a.Hash, b.Hash); + } + + [Fact(DisplayName = "MerkleTree.GetLeafHashes should produce the same leaf hashes that the tree was constructed with")] + public void MerkleTreeGetLeafHashesShouldProduceTheSameLeafHashesThatTheTreeWasConstructedWith() { // Arrange - List hashesForMerkleTreeA = Enumerable - .Range(1, 937) - .Select(i => Hash.ComputeSha2Hash256($"A{i}")) - .ToList(); + MerkleTree candidate = MerkleTree.Create(setA); + + // Act + IEnumerable actual = candidate.GetLeafHashes(); + + // Assert + Assert.Equal(setA, actual); + } - List hashesForMerkleTreeB = Enumerable - .Range(1, 677) - .Select(i => Hash.ComputeSha2Hash256($"B{i}")) + [Fact(DisplayName = "MerkleTree.GetLeafHashes should obtain all leaf hashes from a Merkle tree constructed with 1 million hashes")] + public void MerkleTreeGetLeafHashesShouldObtainAllLeafHashesFromAMerkleTreeConstructedWith1MillionHashes() + { + // Arrange + IEnumerable expected = Enumerable + .Range(0, 1_000_000) + .Select(value => Hash.ComputeSha2Hash256(value.ToString())) .ToList(); + MerkleTree tree = MerkleTree.Create(expected); + // Act - MerkleTree a = MerkleTree.Build(hashesForMerkleTreeA); - MerkleTree b = MerkleTree.Build(hashesForMerkleTreeB); + IEnumerable actual = tree.GetLeafHashes(); // Assert - Assert.NotEqual(a, b); + Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj index 76b5a6a..0af9b5e 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj +++ b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj @@ -1,17 +1,17 @@ - net6.0 + net7.0 false - 10 + 11 - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -22,7 +22,8 @@ - + + diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs index 4d30fff..2a8465f 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs index 7e9088a..39893b5 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs index 91b4d64..0dd6201 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ public void TwoIdenticalPrivateKeysShouldBeConsideredEqual() // Act Base58 base58PrivateKey = privateKey1.ToBase58(); - PrivateKey privateKey2 = RsaPrivateKey.FromBase58(base58PrivateKey, type, padding); + PrivateKey privateKey2 = RsaPrivateKey.Create(base58PrivateKey, type, padding); // Assert Assert.Equal(privateKey1, privateKey2); @@ -49,7 +49,7 @@ public void TwoIdenticalPublicKeysShouldBeConsideredEqual() // Act Base58 base58PublicKey = publicKey1.ToBase58(); - PublicKey publicKey2 = RsaPublicKey.FromBase58(base58PublicKey, type, padding); + PublicKey publicKey2 = RsaPublicKey.Create(base58PublicKey, type, padding); // Assert Assert.Equal(publicKey1, publicKey2); @@ -64,7 +64,7 @@ public void TwoIdenticalRsaKeysShouldBeAbleToSignAndVerifyTheSameData() RSASignaturePadding padding = RSASignaturePadding.Pss; KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = RsaPrivateKey.FromBase64(privateKey1.ToBase64(), type, padding); + PrivateKey privateKey2 = RsaPrivateKey.Create(privateKey1.ToBase64(), type, padding); PublicKey publicKey1 = pair.PublicKey; PublicKey publicKey2 = privateKey1.GetPublicKey(); @@ -96,7 +96,7 @@ public void TwoIdenticalRsaKeysShouldBeAbleToSignAndVerifyTheSameHash() RSASignaturePadding padding = RSASignaturePadding.Pss; KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = RsaPrivateKey.FromBase64(privateKey1.ToBase64(), type, padding); + PrivateKey privateKey2 = RsaPrivateKey.Create(privateKey1.ToBase64(), type, padding); PublicKey publicKey1 = pair.PublicKey; PublicKey publicKey2 = privateKey1.GetPublicKey(); diff --git a/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs b/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs new file mode 100644 index 0000000..59ba584 --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs @@ -0,0 +1,44 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Linq; +using Xunit; + +namespace OnixLabs.Security.Cryptography.UnitTests; + +public sealed class SaltTests +{ + [Fact(DisplayName = "Salt.Create should produce a salt of the specified length")] + public void SaltCreateShouldProduceASaltOfTheSpecifiedLength() + { + // Arrange / Act + const int expected = 32; + Salt candidate = Salt.Create(expected); + + // Assert + Assert.Equal(expected, candidate.ToByteArray().Length); + } + + [Fact(DisplayName = "Salt.CreateNonZero should produce a salt of the specified length of non-zero bytes")] + public void SaltCreateNonZeroShouldProduceASaltOfTheSpecifiedLengthOfNonZeroBytes() + { + // Arrange / Act + const int expected = 32; + Salt candidate = Salt.CreateNonZero(expected); + + // Assert + Assert.Equal(expected, candidate.ToByteArray().Length); + Assert.True(candidate.ToByteArray().All(value => value > 0)); + } +} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs index 1de9700..733421f 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs index e355c65..a72ec1f 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs index 5124b0f..f80bfdb 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs index 3160f2e..1cead0f 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs index 75c363b..954e92e 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -39,6 +39,6 @@ private static string ComputeHash(HashAlgorithm algorithm, string plainText) { byte[] plainTextBytes = Encoding.Default.GetBytes(plainText); byte[] hashedBytes = algorithm.ComputeHash(plainTextBytes); - return Hash.FromByteArray(hashedBytes).ToString(); + return Hash.Create(hashedBytes).ToString(); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs index 2849e64..8ef351c 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs index d36885c..75bd24e 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs index 92f9d71..0f786d2 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -39,6 +39,6 @@ private static string ComputeHash(HashAlgorithm algorithm, string plainText) { byte[] plainTextBytes = Encoding.Default.GetBytes(plainText); byte[] hashedBytes = algorithm.ComputeHash(plainTextBytes); - return Hash.FromByteArray(hashedBytes).ToString(); + return Hash.Create(hashedBytes).ToString(); } } diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Empty.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs similarity index 70% rename from OnixLabs.Security.Cryptography/DigitalSignature.Empty.cs rename to OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs index f64bb8b..b6f137c 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Empty.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; - namespace OnixLabs.Security.Cryptography; public readonly partial struct DigitalSignature @@ -21,13 +19,5 @@ public readonly partial struct DigitalSignature /// /// Gets an empty digital signature value. /// - public static readonly DigitalSignature Empty; - - /// - /// Initializes static members of the class. - /// - static DigitalSignature() - { - Empty = FromByteArray(Array.Empty()); - } + public static DigitalSignature Empty => Create(EmptyArray()); } diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.From.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs similarity index 84% rename from OnixLabs.Security.Cryptography/DigitalSignature.From.cs rename to OnixLabs.Security.Cryptography/DigitalSignature.Create.cs index 27a39b1..7029f35 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.From.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,7 +23,7 @@ public readonly partial struct DigitalSignature /// /// The digitally signed data. /// Returns a instance from the specified digitally signed data. - public static DigitalSignature FromByteArray(byte[] value) + public static DigitalSignature Create(byte[] value) { return new DigitalSignature(value); } @@ -33,10 +33,10 @@ public static DigitalSignature FromByteArray(byte[] value) /// /// The Base-16 from which to construct a signature value. /// Returns an from the specified Base-16 value. - public static DigitalSignature FromBase16(Base16 value) + public static DigitalSignature Create(Base16 value) { byte[] bytes = value.ToByteArray(); - return FromByteArray(bytes); + return Create(bytes); } /// @@ -44,10 +44,10 @@ public static DigitalSignature FromBase16(Base16 value) /// /// The Base-32 from which to construct a signature value. /// Returns an from the specified Base-32 value. - public static DigitalSignature FromBase32(Base32 value) + public static DigitalSignature Create(Base32 value) { byte[] bytes = value.ToByteArray(); - return FromByteArray(bytes); + return Create(bytes); } /// @@ -55,10 +55,10 @@ public static DigitalSignature FromBase32(Base32 value) /// /// The Base-58 from which to construct a signature value. /// Returns an from the specified Base-58 value. - public static DigitalSignature FromBase58(Base58 value) + public static DigitalSignature Create(Base58 value) { byte[] bytes = value.ToByteArray(); - return FromByteArray(bytes); + return Create(bytes); } /// @@ -66,9 +66,9 @@ public static DigitalSignature FromBase58(Base58 value) /// /// The Base-64 from which to construct a signature value. /// Returns an from the specified Base-64 value. - public static DigitalSignature FromBase64(Base64 value) + public static DigitalSignature Create(Base64 value) { byte[] bytes = value.ToByteArray(); - return FromByteArray(bytes); + return Create(bytes); } } diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs index 837007e..b1585fe 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,28 +20,6 @@ namespace OnixLabs.Security.Cryptography; public readonly partial struct DigitalSignature : IEquatable { - /// - /// Performs an equality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(DigitalSignature a, DigitalSignature b) - { - return Equals(a, b); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(DigitalSignature a, DigitalSignature b) - { - return !Equals(a, b); - } - /// /// Checks for equality between this instance and another object. /// @@ -70,4 +48,26 @@ public override int GetHashCode() { return HashCode.Combine(Value.GetContentHashCode()); } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(DigitalSignature left, DigitalSignature right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(DigitalSignature left, DigitalSignature right) + { + return !Equals(left, right); + } } diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs index 85cf729..8bab643 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ public byte[] ToByteArray() /// Returns a value that represents the underlying signature data. public Base16 ToBase16() { - return Base16.FromByteArray(Value); + return Base16.Create(Value); } /// @@ -54,7 +54,7 @@ public Base32 ToBase32() /// Returns a value that represents the underlying signature data. public Base32 ToBase32(Base32Alphabet alphabet) { - return Base32.FromByteArray(Value, alphabet); + return Base32.Create(Value, alphabet); } /// @@ -73,7 +73,7 @@ public Base58 ToBase58() /// Returns a value that represents the underlying signature data. public Base58 ToBase58(Base58Alphabet alphabet) { - return Base58.FromByteArray(Value, alphabet); + return Base58.Create(Value, alphabet); } /// @@ -82,7 +82,7 @@ public Base58 ToBase58(Base58Alphabet alphabet) /// Returns a value that represents the underlying signature data. public Base64 ToBase64() { - return Base64.FromByteArray(Value); + return Base64.Create(Value); } /// diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs index 10920cf..b7b3956 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.cs b/OnixLabs.Security.Cryptography/DigitalSignature.cs index 6ffb8d1..ad3abbb 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; + namespace OnixLabs.Security.Cryptography; /// @@ -25,7 +27,7 @@ public readonly partial struct DigitalSignature /// The digitally signed data. private DigitalSignature(byte[] value) { - Value = value; + Value = value.Copy(); } /// diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.From.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs similarity index 82% rename from OnixLabs.Security.Cryptography/EcdsaPrivateKey.From.cs rename to OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs index e43b3b0..fb6117a 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.From.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; @@ -24,9 +25,9 @@ public sealed partial class EcdsaPrivateKey /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey FromByteArray(byte[] key, HashAlgorithmType type) + public static EcdsaPrivateKey Create(byte[] key, HashAlgorithmType type) { - return new EcdsaPrivateKey(key, type); + return new EcdsaPrivateKey(key.Copy(), type); } /// @@ -35,10 +36,10 @@ public static EcdsaPrivateKey FromByteArray(byte[] key, HashAlgorithmType type) /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey FromBase16(Base16 key, HashAlgorithmType type) + public static EcdsaPrivateKey Create(Base16 key, HashAlgorithmType type) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } /// @@ -47,10 +48,10 @@ public static EcdsaPrivateKey FromBase16(Base16 key, HashAlgorithmType type) /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey FromBase32(Base32 key, HashAlgorithmType type) + public static EcdsaPrivateKey Create(Base32 key, HashAlgorithmType type) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } /// @@ -59,10 +60,10 @@ public static EcdsaPrivateKey FromBase32(Base32 key, HashAlgorithmType type) /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey FromBase58(Base58 key, HashAlgorithmType type) + public static EcdsaPrivateKey Create(Base58 key, HashAlgorithmType type) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } /// @@ -71,9 +72,9 @@ public static EcdsaPrivateKey FromBase58(Base58 key, HashAlgorithmType type) /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey FromBase64(Base64 key, HashAlgorithmType type) + public static EcdsaPrivateKey Create(Base64 key, HashAlgorithmType type) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs index 73f6f0f..cadf8d1 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,9 +26,7 @@ public sealed partial class EcdsaPrivateKey public override byte[] ExportPkcs8Key() { using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); - return privateKey.ExportPkcs8PrivateKey(); } @@ -41,9 +39,7 @@ public override byte[] ExportPkcs8Key() public override byte[] ExportPkcs8Key(ReadOnlySpan password, PbeParameters parameters) { using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); - return privateKey.ExportEncryptedPkcs8PrivateKey(password, parameters); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs index 91cfb79..e5299ae 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -25,10 +25,8 @@ public sealed partial class EcdsaPrivateKey public override PublicKey GetPublicKey() { using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); byte[] publicKey = privateKey.ExportSubjectPublicKeyInfo(); - return new EcdsaPublicKey(publicKey, AlgorithmType); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs index ac3559e..fe313b6 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,11 +28,9 @@ public sealed partial class EcdsaPrivateKey public static EcdsaPrivateKey ImportPkcs8Key(ReadOnlySpan data, HashAlgorithmType type) { ECDsa privateKey = ECDsa.Create(); - privateKey.ImportPkcs8PrivateKey(data, out int _); byte[] bytes = privateKey.ExportECPrivateKey(); - - return FromByteArray(bytes, type); + return Create(bytes, type); } /// @@ -57,11 +55,9 @@ public static EcdsaPrivateKey ImportPkcs8Key(byte[] data, HashAlgorithmType type public static EcdsaPrivateKey ImportPkcs8Key(ReadOnlySpan data, ReadOnlySpan password, HashAlgorithmType type) { ECDsa privateKey = ECDsa.Create(); - privateKey.ImportEncryptedPkcs8PrivateKey(password, data, out int _); byte[] bytes = privateKey.ExportECPrivateKey(); - - return FromByteArray(bytes, type); + return Create(bytes, type); } /// diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs index a47a64d..9fef639 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,12 +26,10 @@ public sealed partial class EcdsaPrivateKey public override DigitalSignature SignData(byte[] unsignedData) { using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); byte[] signedData = privateKey.SignData(unsignedData, name); - - return DigitalSignature.FromByteArray(signedData); + return DigitalSignature.Create(signedData); } /// @@ -42,10 +40,8 @@ public override DigitalSignature SignData(byte[] unsignedData) public override DigitalSignature SignHash(byte[] unsignedHash) { using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); byte[] signedData = privateKey.SignHash(unsignedHash); - - return DigitalSignature.FromByteArray(signedData); + return DigitalSignature.Create(signedData); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs index 48fad76..67f2cac 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.From.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs similarity index 82% rename from OnixLabs.Security.Cryptography/EcdsaPublicKey.From.cs rename to OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs index 125755f..9f08b21 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.From.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; @@ -24,9 +25,9 @@ public sealed partial class EcdsaPublicKey /// The key data from which to construct a public key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey FromByteArray(byte[] key, HashAlgorithmType type) + public static EcdsaPublicKey Create(byte[] key, HashAlgorithmType type) { - return new EcdsaPublicKey(key, type); + return new EcdsaPublicKey(key.Copy(), type); } /// @@ -35,10 +36,10 @@ public static EcdsaPublicKey FromByteArray(byte[] key, HashAlgorithmType type) /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey FromBase16(Base16 key, HashAlgorithmType type) + public static EcdsaPublicKey Create(Base16 key, HashAlgorithmType type) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } /// @@ -47,10 +48,10 @@ public static EcdsaPublicKey FromBase16(Base16 key, HashAlgorithmType type) /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey FromBase32(Base32 key, HashAlgorithmType type) + public static EcdsaPublicKey Create(Base32 key, HashAlgorithmType type) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } /// @@ -59,10 +60,10 @@ public static EcdsaPublicKey FromBase32(Base32 key, HashAlgorithmType type) /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey FromBase58(Base58 key, HashAlgorithmType type) + public static EcdsaPublicKey Create(Base58 key, HashAlgorithmType type) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } /// @@ -71,9 +72,9 @@ public static EcdsaPublicKey FromBase58(Base58 key, HashAlgorithmType type) /// The key data from which to construct a private key. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey FromBase64(Base64 key, HashAlgorithmType type) + public static EcdsaPublicKey Create(Base64 key, HashAlgorithmType type) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs index bd44b43..2fb025d 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,11 +27,9 @@ public sealed partial class EcdsaPublicKey public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData) { using ECDsa publicKey = ECDsa.Create(); - publicKey.ImportSubjectPublicKeyInfo(KeyData, out int _); byte[] signatureData = signature.ToByteArray(); HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - return publicKey.VerifyData(unsignedData, signatureData, name); } @@ -44,10 +42,8 @@ public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData public override bool IsHashValid(DigitalSignature signature, byte[] unsignedHash) { using ECDsa publicKey = ECDsa.Create(); - publicKey.ImportSubjectPublicKeyInfo(KeyData, out int _); byte[] signatureData = signature.ToByteArray(); - return publicKey.VerifyHash(unsignedHash, signatureData); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs index 1af352b..9fe126c 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs b/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs index 94beba4..257a47b 100644 --- a/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs +++ b/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ using System; using System.Linq; -using static OnixLabs.Core.Preconditions; namespace OnixLabs.Security.Cryptography; @@ -49,9 +48,8 @@ public static Hash CreateAllOneHash(HashAlgorithmType type) /// If the length of the hash is unexpected. public static Hash CreateAllOneHash(HashAlgorithmType type, int length) { - Check(type.IsUnknown || type.Length == length, "Unexpected hash algorithm output length."); - + Require(type.IsUnknown || type.Length == length, "Unexpected hash algorithm output length.", nameof(length)); byte[] bytes = Enumerable.Repeat(byte.MaxValue, length).ToArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } } diff --git a/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs b/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs index 5985b43..c620bce 100644 --- a/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs +++ b/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ using System; using System.Linq; -using static OnixLabs.Core.Preconditions; namespace OnixLabs.Security.Cryptography; @@ -49,9 +48,8 @@ public static Hash CreateAllZeroHash(HashAlgorithmType type) /// If the length of the hash is unexpected. public static Hash CreateAllZeroHash(HashAlgorithmType type, int length) { - Check(type.IsUnknown || type.Length == length, "Unexpected hash algorithm output length."); - + Require(type.IsUnknown || type.Length == length, "Unexpected hash algorithm output length.", nameof(length)); byte[] bytes = Enumerable.Repeat(byte.MinValue, length).ToArray(); - return FromByteArray(bytes, type); + return Create(bytes, type); } } diff --git a/OnixLabs.Security.Cryptography/Hash.Comparable.cs b/OnixLabs.Security.Cryptography/Hash.Comparable.cs new file mode 100644 index 0000000..932689b --- /dev/null +++ b/OnixLabs.Security.Cryptography/Hash.Comparable.cs @@ -0,0 +1,35 @@ +using System; +using System.Numerics; +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography; + +public readonly partial struct Hash : IComparable, IComparable +{ + /// + /// Compares the current instance with another object of the same type and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other object. + /// + /// An object to compare with this instance. + /// Returns a value that indicates the relative order of the objects being compared. + public int CompareTo(object? obj) + { + return this.CompareObject(obj); + } + + /// + /// Compares the current instance with another object of the same type and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other object. + /// + /// An object to compare with this instance. + /// Returns a value that indicates the relative order of the objects being compared. + public int CompareTo(Hash other) + { + BigInteger left = new(ToByteArray()); + BigInteger right = new(other.ToByteArray()); + + return left.CompareTo(right); + } +} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs index 3272729..99d1df4 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs index f55d934..7e7a644 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs index e19fd63..323b418 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs index 8b1c0f1..f219c2f 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs index d310bd6..a2fb9f3 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs index 64e6a74..ed9d218 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs index 6346596..d96126e 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs index 6ab1e42..e32133a 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs index 6c2c34b..c3785c9 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs index c94f57b..ff62fd8 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs index d1cd45e..5005481 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.cs b/OnixLabs.Security.Cryptography/Hash.Compute.cs index 32ebeea..d861f01 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -77,7 +77,7 @@ public static Hash ComputeHash(byte[] value, HashAlgorithmType type) { using HashAlgorithm algorithm = type.GetHashAlgorithm(); byte[] hashedValue = algorithm.ComputeHash(value); - return FromByteArray(hashedValue, type); + return Create(hashedValue, type); } /// @@ -91,6 +91,6 @@ public static Hash ComputeHash(byte[] value, HashAlgorithmType type, int length) { using HashAlgorithm algorithm = type.GetHashAlgorithm(length); byte[] hashedValue = algorithm.ComputeHash(value); - return FromByteArray(hashedValue, type); + return Create(hashedValue, type); } } diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs index 65c5509..ed6d011 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs index 9261255..14e092d 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs index 3fa2372..7b3afb7 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs index 0e329c6..7f32ee7 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs index 43d7fbc..fdc32a7 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs index 165702a..9a2784b 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs index 19378c7..d2991ba 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs index b48436a..0084c4c 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs index a6717c9..5e459b1 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs index 102ac35..5ad5063 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs index 96e5d02..0c6346e 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs index 04f8532..926e239 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -80,7 +80,7 @@ public static async Task ComputeHashAsync(byte[] value, HashAlgorithmType using HashAlgorithm algorithm = type.GetHashAlgorithm(); await using Stream stream = new MemoryStream(value); byte[] hashedValue = await algorithm.ComputeHashAsync(stream); - return FromByteArray(hashedValue, type); + return Create(hashedValue, type); } /// @@ -95,6 +95,6 @@ public static async Task ComputeHashAsync(byte[] value, HashAlgorithmType using HashAlgorithm algorithm = type.GetHashAlgorithm(length); await using Stream stream = new MemoryStream(value); byte[] hashedValue = await algorithm.ComputeHashAsync(stream); - return FromByteArray(hashedValue, type); + return Create(hashedValue, type); } } diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs b/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs index e4b0eb7..27c88d0 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -78,7 +78,7 @@ public static Hash ComputeHashTwice(byte[] value, HashAlgorithmType type) using HashAlgorithm algorithm = type.GetHashAlgorithm(); byte[] firstRoundValue = algorithm.ComputeHash(value); byte[] secondRoundValue = algorithm.ComputeHash(firstRoundValue); - return FromByteArray(secondRoundValue, type); + return Create(secondRoundValue, type); } /// @@ -93,6 +93,6 @@ public static Hash ComputeHashTwice(byte[] value, HashAlgorithmType type, int le using HashAlgorithm algorithm = type.GetHashAlgorithm(length); byte[] firstRoundValue = algorithm.ComputeHash(value); byte[] secondRoundValue = algorithm.ComputeHash(firstRoundValue); - return FromByteArray(secondRoundValue, type); + return Create(secondRoundValue, type); } } diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs b/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs index 7d05fd1..983f8d3 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -85,7 +85,7 @@ public static async Task ComputeHashTwiceAsync(byte[] value, HashAlgorithm await using Stream secondRoundStream = new MemoryStream(firstRoundValue); byte[] secondRoundValue = await algorithm.ComputeHashAsync(secondRoundStream); - return FromByteArray(secondRoundValue, type); + return Create(secondRoundValue, type); } /// @@ -105,6 +105,6 @@ public static async Task ComputeHashTwiceAsync(byte[] value, HashAlgorithm await using Stream secondRoundStream = new MemoryStream(firstRoundValue); byte[] secondRoundValue = await algorithm.ComputeHashAsync(secondRoundStream); - return FromByteArray(secondRoundValue, type); + return Create(secondRoundValue, type); } } diff --git a/OnixLabs.Security.Cryptography/Hash.Concantenate.cs b/OnixLabs.Security.Cryptography/Hash.Concantenate.cs index 05163bf..d1e21f9 100644 --- a/OnixLabs.Security.Cryptography/Hash.Concantenate.cs +++ b/OnixLabs.Security.Cryptography/Hash.Concantenate.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,10 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Linq; using System.Security.Cryptography; -using static OnixLabs.Core.Preconditions; namespace OnixLabs.Security.Cryptography; @@ -29,13 +27,11 @@ public readonly partial struct Hash /// Returns the concatenation of the two instances. public static Hash Concatenate(Hash a, Hash b) { - Check(a.AlgorithmType == b.AlgorithmType, "Cannot concatenate hashes of different algorithm types."); - + Require(a.AlgorithmType == b.AlgorithmType, "Cannot concatenate hashes of different algorithm types."); using HashAlgorithm algorithm = a.AlgorithmType.GetHashAlgorithm(); byte[] concatenatedValue = a.ToByteArray().Concat(b.ToByteArray()).ToArray(); byte[] hashedValue = algorithm.ComputeHash(concatenatedValue); - - return FromByteArray(hashedValue, a.AlgorithmType); + return Create(hashedValue, a.AlgorithmType); } /// @@ -47,12 +43,11 @@ public static Hash Concatenate(Hash a, Hash b) /// Returns the concatenation of the two instances. public static Hash Concatenate(Hash a, Hash b, int length) { - Check(a.AlgorithmType == b.AlgorithmType, "Cannot concatenate hashes of different algorithm types."); - + Require(a.AlgorithmType == b.AlgorithmType, "Cannot concatenate hashes of different algorithm types."); using HashAlgorithm algorithm = a.AlgorithmType.GetHashAlgorithm(length); byte[] concatenatedValue = a.ToByteArray().Concat(b.ToByteArray()).ToArray(); byte[] hashedValue = algorithm.ComputeHash(concatenatedValue); - return FromByteArray(hashedValue, a.AlgorithmType); + return Create(hashedValue, a.AlgorithmType); } /// diff --git a/OnixLabs.Security.Cryptography/Hash.Empty.cs b/OnixLabs.Security.Cryptography/Hash.Constants.cs similarity index 70% rename from OnixLabs.Security.Cryptography/Hash.Empty.cs rename to OnixLabs.Security.Cryptography/Hash.Constants.cs index b5bb1a1..8f85ebe 100644 --- a/OnixLabs.Security.Cryptography/Hash.Empty.cs +++ b/OnixLabs.Security.Cryptography/Hash.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; - namespace OnixLabs.Security.Cryptography; public readonly partial struct Hash @@ -21,13 +19,5 @@ public readonly partial struct Hash /// /// Gets an empty hash value. /// - public static readonly Hash Empty; - - /// - /// Initializes static members of the class. - /// - static Hash() - { - Empty = FromByteArray(Array.Empty(), HashAlgorithmType.Unknown); - } + public static Hash Empty => Create(EmptyArray()); } diff --git a/OnixLabs.Security.Cryptography/Hash.From.cs b/OnixLabs.Security.Cryptography/Hash.Create.cs similarity index 82% rename from OnixLabs.Security.Cryptography/Hash.From.cs rename to OnixLabs.Security.Cryptography/Hash.Create.cs index 7dec22c..6b0b2da 100644 --- a/OnixLabs.Security.Cryptography/Hash.From.cs +++ b/OnixLabs.Security.Cryptography/Hash.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; @@ -24,9 +25,9 @@ public readonly partial struct Hash /// /// The array to represent as a hash. /// A new instance. - public static Hash FromByteArray(byte[] value) + public static Hash Create(byte[] value) { - return FromByteArray(value, HashAlgorithmType.Unknown); + return Create(value, HashAlgorithmType.Unknown); } /// @@ -35,9 +36,9 @@ public static Hash FromByteArray(byte[] value) /// The array to represent as a hash. /// The hash algorithm type of the hash. /// A new instance. - public static Hash FromByteArray(byte[] value, HashAlgorithmType type) + public static Hash Create(byte[] value, HashAlgorithmType type) { - return new Hash(value, type); + return new Hash(value.Copy(), type); } /// @@ -45,10 +46,10 @@ public static Hash FromByteArray(byte[] value, HashAlgorithmType type) /// /// The Base-16 from which to construct a hash value. /// Returns an from the specified Base-16 value. - public static Hash FromBase16(Base16 value) + public static Hash Create(Base16 value) { byte[] bytes = value.ToByteArray(); - return FromByteArray(bytes); + return Create(bytes); } /// @@ -56,10 +57,10 @@ public static Hash FromBase16(Base16 value) /// /// The Base-32 from which to construct a hash value. /// Returns an from the specified Base-32 value. - public static Hash FromBase32(Base32 value) + public static Hash Create(Base32 value) { byte[] bytes = value.ToByteArray(); - return FromByteArray(bytes); + return Create(bytes); } /// @@ -67,10 +68,10 @@ public static Hash FromBase32(Base32 value) /// /// The Base-58 from which to construct a hash value. /// Returns an from the specified Base-58 value. - public static Hash FromBase58(Base58 value) + public static Hash Create(Base58 value) { byte[] bytes = value.ToByteArray(); - return FromByteArray(bytes); + return Create(bytes); } /// @@ -78,9 +79,9 @@ public static Hash FromBase58(Base58 value) /// /// The Base-64 from which to construct a hash value. /// Returns an from the specified Base-64 value. - public static Hash FromBase64(Base64 value) + public static Hash Create(Base64 value) { byte[] bytes = value.ToByteArray(); - return FromByteArray(bytes); + return Create(bytes); } } diff --git a/OnixLabs.Security.Cryptography/Hash.Equatable.cs b/OnixLabs.Security.Cryptography/Hash.Equatable.cs index 14b77dc..61c475e 100644 --- a/OnixLabs.Security.Cryptography/Hash.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Hash.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,28 +20,6 @@ namespace OnixLabs.Security.Cryptography; public readonly partial struct Hash : IEquatable { - /// - /// Performs an equality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(Hash a, Hash b) - { - return Equals(a, b); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(Hash a, Hash b) - { - return !Equals(a, b); - } - /// /// Checks for equality between this instance and another object. /// @@ -70,4 +48,26 @@ public override int GetHashCode() { return HashCode.Combine(AlgorithmType, Value.GetContentHashCode()); } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(Hash left, Hash right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(Hash left, Hash right) + { + return !Equals(left, right); + } } diff --git a/OnixLabs.Security.Cryptography/Hash.Parse.cs b/OnixLabs.Security.Cryptography/Hash.Parse.cs index 0806815..8155dac 100644 --- a/OnixLabs.Security.Cryptography/Hash.Parse.cs +++ b/OnixLabs.Security.Cryptography/Hash.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ public static Hash Parse(string value, HashAlgorithmType? type = null) CheckMatchingHashAlgorithms(parsedType, type); } - return FromByteArray(parsedValue, parsedType); + return Create(parsedValue, parsedType); } /// @@ -67,7 +67,7 @@ public static bool TryParse(string value, HashAlgorithmType? type, out Hash hash private static HashAlgorithmType GetParsedHashAlgorithmType(string value) { string defaultHashAlgorithmType = HashAlgorithmType.Unknown.Name; - string parsedType = value.SubstringBefore(':', defaultHashAlgorithmType); + string parsedType = value.SubstringBeforeFirst(':', defaultHashAlgorithmType); return HashAlgorithmType.FromName(parsedType); } @@ -78,7 +78,7 @@ private static HashAlgorithmType GetParsedHashAlgorithmType(string value) /// Returns a array from the specified value. private static byte[] GetParsedHashValue(string value) { - string parsedValue = value.SubstringAfter(':'); + string parsedValue = value.SubstringAfterFirst(':'); return Convert.FromHexString(parsedValue); } diff --git a/OnixLabs.Security.Cryptography/Hash.To.cs b/OnixLabs.Security.Cryptography/Hash.To.cs index f086e86..4abef60 100644 --- a/OnixLabs.Security.Cryptography/Hash.To.cs +++ b/OnixLabs.Security.Cryptography/Hash.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ public byte[] ToByteArray() /// Returns a value that represents the underlying hash data. public Base16 ToBase16() { - return Base16.FromByteArray(Value); + return Base16.Create(Value); } /// @@ -54,7 +54,7 @@ public Base32 ToBase32() /// Returns a value that represents the underlying hash data. public Base32 ToBase32(Base32Alphabet alphabet) { - return Base32.FromByteArray(Value, alphabet); + return Base32.Create(Value, alphabet); } /// @@ -73,7 +73,7 @@ public Base58 ToBase58() /// Returns a value that represents the underlying hash data. public Base58 ToBase58(Base58Alphabet alphabet) { - return Base58.FromByteArray(Value, alphabet); + return Base58.Create(Value, alphabet); } /// @@ -82,7 +82,7 @@ public Base58 ToBase58(Base58Alphabet alphabet) /// Returns a value that represents the underlying hash data. public Base64 ToBase64() { - return Base64.FromByteArray(Value); + return Base64.Create(Value); } /// diff --git a/OnixLabs.Security.Cryptography/Hash.cs b/OnixLabs.Security.Cryptography/Hash.cs index fe2903a..e31eb1f 100644 --- a/OnixLabs.Security.Cryptography/Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; + namespace OnixLabs.Security.Cryptography; /// @@ -27,9 +29,8 @@ public readonly partial struct Hash private Hash(byte[] value, HashAlgorithmType type) { type.VerifyHashLength(value); - AlgorithmType = type; - Value = value; + Value = value.Copy(); } /// diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs index a359816..ad53ecf 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs index e8de590..7c96a8b 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,7 +14,6 @@ using System; using System.Security.Cryptography; -using static OnixLabs.Core.Preconditions; namespace OnixLabs.Security.Cryptography; @@ -38,7 +37,7 @@ public HashAlgorithm GetHashAlgorithm() /// If the hash algorithm is unknown. public HashAlgorithm GetHashAlgorithm(int length) { - Check(IsUnknown || length == Length, $"Output length not expected for the specified hash algorithm: {Name}"); + Require(IsUnknown || length == Length, $"Output length not expected for the specified hash algorithm: {Name}", nameof(length)); return Name switch { diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs index 21065a7..21be3ae 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ // limitations under the License. using System; -using static OnixLabs.Core.Preconditions; namespace OnixLabs.Security.Cryptography; @@ -36,6 +35,6 @@ public bool IsValidHashLength(byte[] value) /// If the length of the byte array is invalid. public void VerifyHashLength(byte[] value) { - Check(IsValidHashLength(value), "The length of the hash is invalid.", nameof(value)); + Require(IsValidHashLength(value), "The length of the hash is invalid.", nameof(value)); } } diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.cs index ada1def..567d918 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs index d1cf46f..4b1d21e 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -41,7 +41,6 @@ public static Hmac ComputeMd5Hmac(string value, string key, Encoding encoding) { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return ComputeMd5Hmac(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs index 5c63312..5ef8bfd 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -41,7 +41,6 @@ public static Hmac ComputeSha1Hmac(string value, string key, Encoding encoding) { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return ComputeSha1Hmac(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs index d936676..b839db3 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -41,7 +41,6 @@ public static Hmac ComputeSha2Hmac256(string value, string key, Encoding encodin { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return ComputeSha2Hmac256(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs index c05966d..494c1b4 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -41,7 +41,6 @@ public static Hmac ComputeSha2Hmac384(string value, string key, Encoding encodin { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return ComputeSha2Hmac384(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs index b390832..b10ee8f 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -41,7 +41,6 @@ public static Hmac ComputeSha2Hmac512(string value, string key, Encoding encodin { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return ComputeSha2Hmac512(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.cs index 1fc842f..71de157 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -43,7 +43,6 @@ public static Hmac ComputeHmac(string value, string key, HashAlgorithmType type, { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return ComputeHmac(valueBytes, keyBytes, type); } @@ -57,10 +56,8 @@ public static Hmac ComputeHmac(string value, string key, HashAlgorithmType type, public static Hmac ComputeHmac(byte[] value, byte[] key, HashAlgorithmType type) { using KeyedHashAlgorithm algorithm = type.GetKeyedHashAlgorithm(key); - byte[] data = algorithm.ComputeHash(value); - Hash hash = Hash.FromByteArray(data, type); - + Hash hash = Hash.Create(data, type); return Create(hash, value); } } diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs index e246790..f32c44a 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -42,7 +42,6 @@ public static async Task ComputeMd5HmacAsync(string value, string key, Enc { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return await ComputeMd5HmacAsync(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs index 46fb8d0..0a57030 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -42,7 +42,6 @@ public static async Task ComputeSha1HmacAsync(string value, string key, En { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return await ComputeSha1HmacAsync(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs index 43bf383..219cd1c 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -42,7 +42,6 @@ public static async Task ComputeSha2Hmac256Async(string value, string key, { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return await ComputeSha2Hmac256Async(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs index 1bf5ad2..22c4855 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -42,7 +42,6 @@ public static async Task ComputeSha2Hmac384Async(string value, string key, { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return await ComputeSha2Hmac384Async(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs index c2cc2ff..e6345e8 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -42,7 +42,6 @@ public static async Task ComputeSha2Hmac512Async(string value, string key, { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return await ComputeSha2Hmac512Async(valueBytes, keyBytes); } diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs index f09bf8b..a0bc69a 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -45,7 +45,6 @@ public static async Task ComputeHmacAsync(string value, string key, HashAl { byte[] valueBytes = encoding.GetBytes(value); byte[] keyBytes = encoding.GetBytes(key); - return await ComputeHmacAsync(valueBytes, keyBytes, type); } @@ -62,7 +61,7 @@ public static async Task ComputeHmacAsync(byte[] value, byte[] key, HashAl await using Stream stream = new MemoryStream(value); byte[] data = await algorithm.ComputeHashAsync(stream); - Hash hash = Hash.FromByteArray(data, type); + Hash hash = Hash.Create(data, type); return Create(hash, value); } diff --git a/OnixLabs.Security.Cryptography/Hmac.Empty.cs b/OnixLabs.Security.Cryptography/Hmac.Constants.cs similarity index 72% rename from OnixLabs.Security.Cryptography/Hmac.Empty.cs rename to OnixLabs.Security.Cryptography/Hmac.Constants.cs index dcf141d..0436605 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Empty.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; - namespace OnixLabs.Security.Cryptography; public readonly partial struct Hmac @@ -21,13 +19,5 @@ public readonly partial struct Hmac /// /// Gets an empty hashed message authentication code (HMAC) value. /// - public static readonly Hmac Empty; - - /// - /// Initializes static members of the class. - /// - static Hmac() - { - Empty = Create(Hash.Empty, Array.Empty()); - } + public static Hmac Empty => Create(Hash.Empty, EmptyArray()); } diff --git a/OnixLabs.Security.Cryptography/Hmac.Create.cs b/OnixLabs.Security.Cryptography/Hmac.Create.cs index 2ddc8ca..c22f53f 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Create.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; + namespace OnixLabs.Security.Cryptography; public readonly partial struct Hmac @@ -24,6 +26,6 @@ public readonly partial struct Hmac /// Returns a new instance. public static Hmac Create(Hash hash, byte[] data) { - return new Hmac(hash, data); + return new Hmac(hash, data.Copy()); } } diff --git a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs index c418ded..b75e99b 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,28 +20,6 @@ namespace OnixLabs.Security.Cryptography; public readonly partial struct Hmac : IEquatable { - /// - /// Performs an equality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(Hmac a, Hmac b) - { - return Equals(a, b); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(Hmac a, Hmac b) - { - return !Equals(a, b); - } - /// /// Checks for equality between this instance and another object. /// @@ -70,4 +48,26 @@ public override int GetHashCode() { return HashCode.Combine(Hash, Data.GetContentHashCode()); } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(Hmac left, Hmac right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(Hmac left, Hmac right) + { + return !Equals(left, right); + } } diff --git a/OnixLabs.Security.Cryptography/Hmac.Parse.cs b/OnixLabs.Security.Cryptography/Hmac.Parse.cs index d8633b3..e28cb38 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Parse.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.To.cs b/OnixLabs.Security.Cryptography/Hmac.To.cs index f37933c..77d053d 100644 --- a/OnixLabs.Security.Cryptography/Hmac.To.cs +++ b/OnixLabs.Security.Cryptography/Hmac.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Verify.cs b/OnixLabs.Security.Cryptography/Hmac.Verify.cs index 63161ac..8e7e78d 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Verify.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.cs index 019cbf6..08b76f7 100644 --- a/OnixLabs.Security.Cryptography/Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -34,7 +34,7 @@ public readonly partial struct Hmac private Hmac(Hash hash, byte[] data) { Hash = hash; - this.data = data; + this.data = data.Copy(); } /// diff --git a/OnixLabs.Security.Cryptography/IHashable.cs b/OnixLabs.Security.Cryptography/IHashable.cs new file mode 100644 index 0000000..fff2f8f --- /dev/null +++ b/OnixLabs.Security.Cryptography/IHashable.cs @@ -0,0 +1,27 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Security.Cryptography; + +/// +/// Defines a mechanism for computing the hash of a data structure. +/// +public interface IHashable +{ + /// + /// Computes the hash of the current object. + /// + /// Return the computed hash of the current object. + Hash ComputeHash(); +} diff --git a/OnixLabs.Security.Cryptography/KeyPair.Create.cs b/OnixLabs.Security.Cryptography/KeyPair.Create.cs index d34348a..ecaa985 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.Create.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs index 51b2248..ed5d5f0 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,28 +18,6 @@ namespace OnixLabs.Security.Cryptography; public sealed partial class KeyPair : IEquatable { - /// - /// Performs an equality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(KeyPair a, KeyPair b) - { - return Equals(a, b); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(KeyPair a, KeyPair b) - { - return !Equals(a, b); - } - /// /// Checks for equality between this instance and another object. /// @@ -71,4 +49,26 @@ public override int GetHashCode() { return HashCode.Combine(PrivateKey, PublicKey); } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(KeyPair left, KeyPair right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(KeyPair left, KeyPair right) + { + return !Equals(left, right); + } } diff --git a/OnixLabs.Security.Cryptography/KeyPair.From.cs b/OnixLabs.Security.Cryptography/KeyPair.From.cs index 5120d94..f1e4387 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.From.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.From.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ // limitations under the License. using System; -using static OnixLabs.Core.Preconditions; namespace OnixLabs.Security.Cryptography; @@ -31,8 +30,8 @@ public sealed partial class KeyPair /// If the private and public key components are mismatched. public static KeyPair FromKeyComponents(PrivateKey privateKey, PublicKey publicKey, HashAlgorithmType type) { - Check(privateKey.AlgorithmType == type, $"Private key hash algorithm type is mismatched with '{type}'.", nameof(privateKey)); - Check(publicKey.AlgorithmType == type, $"Public key hash algorithm type is mismatched with '{type}'.", nameof(publicKey)); + Require(privateKey.AlgorithmType == type, $"Private key hash algorithm type is mismatched with '{type}'.", nameof(privateKey)); + Require(publicKey.AlgorithmType == type, $"Public key hash algorithm type is mismatched with '{type}'.", nameof(publicKey)); byte[] random = Guid.NewGuid().ToByteArray(); Hash hash = Hash.ComputeSha2Hash256(random); diff --git a/OnixLabs.Security.Cryptography/KeyPair.cs b/OnixLabs.Security.Cryptography/KeyPair.cs index 420b2fb..501601e 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Build.cs b/OnixLabs.Security.Cryptography/MerkleTree.Build.cs new file mode 100644 index 0000000..26f30d4 --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.Build.cs @@ -0,0 +1,103 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using System.Linq; +using OnixLabs.Core.Linq; + +namespace OnixLabs.Security.Cryptography; + +public abstract partial class MerkleTree +{ + /// + /// Creates a from the specified leaves. + /// + /// The leaves from which to create a . + /// Returns a new computed from the specified leaves. + public static MerkleTree Create(params Hash[] leaves) + { + return Create(leaves.ToList()); + } + + /// + /// Creates a from the specified leaves. + /// + /// The leaves from which to create a . + /// Returns a new computed from the specified leaves. + public static MerkleTree Create(IEnumerable leaves) + { + IReadOnlyList nodes = leaves.Select(leaf => new MerkleTreeLeafNode(leaf)).ToList(); + + Require(nodes.IsNotEmpty(), + "Cannot construct a merkle tree from an empty list.", nameof(nodes)); + + Require(nodes.AllEqualBy(merkleTree => merkleTree.Hash.AlgorithmType), + "Cannot construct a merkle tree with different hash algorithm types.", nameof(nodes)); + + return Create(nodes); + } + + /// + /// Creates a from the specified leaves. + /// + /// The leaves from which to create a . + /// Returns a new computed from the specified leaves. + public static MerkleTree Create(params T[] leaves) where T : IHashable + { + return MerkleTree.Create(leaves); + } + + /// + /// Creates a from the specified leaves. + /// + /// The leaves from which to create a . + /// Returns a new computed from the specified leaves. + public static MerkleTree Create(IEnumerable leaves) where T : IHashable + { + return MerkleTree.Create(leaves); + } + + /// + /// Creates a from the specified leaves. + /// + /// The leaves from which to create a . + /// Returns a new computed from the specified leaves. + private static MerkleTree Create(IReadOnlyList nodes) + { + while (true) + { + if (nodes.IsSingle()) + { + return nodes.Single(); + } + + if (nodes.IsCountOdd()) + { + HashAlgorithmType type = nodes[0].Hash.AlgorithmType; + nodes = nodes.Append(new MerkleTreeEmptyNode(type)).ToList(); + } + + List mergedNodes = new(); + + for (int index = 0; index < nodes.Count; index += 2) + { + MerkleTree left = nodes[index]; + MerkleTree right = nodes[index + 1]; + mergedNodes.Add(new MerkleTreeBranchNode(left, right)); + } + + nodes = mergedNodes; + } + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs b/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs index 0469861..87e4e2e 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,28 +18,6 @@ namespace OnixLabs.Security.Cryptography; public abstract partial class MerkleTree : IEquatable { - /// - /// Performs an equality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(MerkleTree a, MerkleTree b) - { - return Equals(a, b); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(MerkleTree a, MerkleTree b) - { - return !Equals(a, b); - } - /// /// Checks for equality between this instance and another object. /// @@ -68,4 +46,26 @@ public override int GetHashCode() { return HashCode.Combine(GetType(), Hash); } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(MerkleTree left, MerkleTree right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(MerkleTree left, MerkleTree right) + { + return !Equals(left, right); + } } diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs new file mode 100644 index 0000000..8f690b4 --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs @@ -0,0 +1,83 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using System.Linq; +using OnixLabs.Core.Linq; + +namespace OnixLabs.Security.Cryptography; + +public abstract partial class MerkleTree +{ + /// + /// Creates a from the specified leaves. + /// + /// The leaves from which to create a . + /// Returns a new computed from the specified leaves. + public static MerkleTree Create(params T[] leaves) + { + return Create(leaves.ToList()); + } + + /// + /// Creates a from the specified leaves. + /// + /// The leaves from which to create a . + /// Returns a new computed from the specified leaves. + public static MerkleTree Create(IEnumerable leaves) + { + IReadOnlyList> nodes = leaves.Select(leaf => new MerkleTreeLeafNode(leaf)).ToList(); + + Require(nodes.IsNotEmpty(), + "Cannot construct a merkle tree from an empty list.", nameof(nodes)); + + Require(nodes.AllEqualBy(merkleTree => merkleTree.Hash.AlgorithmType), + "Cannot construct a merkle tree with different hash types.", nameof(nodes)); + + return Create(nodes); + } + + /// + /// Creates a from the specified leaves. + /// + /// The leaves from which to create a . + /// Returns a new computed from the specified leaves. + private static MerkleTree Create(IReadOnlyList> nodes) + { + while (true) + { + if (nodes.IsSingle()) + { + return nodes.Single(); + } + + if (nodes.IsCountOdd()) + { + HashAlgorithmType type = nodes[0].Hash.AlgorithmType; + nodes = nodes.Append(new MerkleTreeEmptyNode(type)).ToList(); + } + + List> mergedNodes = new(); + + for (int index = 0; index < nodes.Count; index += 2) + { + MerkleTree left = nodes[index]; + MerkleTree right = nodes[index + 1]; + mergedNodes.Add(new MerkleTreeBranchNode(left, right)); + } + + nodes = mergedNodes; + } + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs new file mode 100644 index 0000000..2a0c3f5 --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs @@ -0,0 +1,71 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Security.Cryptography; + +public abstract partial class MerkleTree : IEquatable> +{ + /// + /// Checks for equality between this instance and another object. + /// + /// The object to check for equality. + /// true if the object is equal to this instance; otherwise, false. + public virtual bool Equals(MerkleTree? other) + { + return ReferenceEquals(this, other) || other is not null && other.Hash == Hash; + } + + /// + /// Checks for equality between this instance and another object. + /// + /// The object to check for equality. + /// true if the object is equal to this instance; otherwise, false. + public override bool Equals(object? obj) + { + return Equals(obj as MerkleTree); + } + + /// + /// Serves as a hash code function for this instance. + /// + /// A hash code for this instance. + public override int GetHashCode() + { + return HashCode.Combine(GetType(), Hash); + } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(MerkleTree left, MerkleTree right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(MerkleTree left, MerkleTree right) + { + return !Equals(left, right); + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs new file mode 100644 index 0000000..acae77b --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs @@ -0,0 +1,80 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace OnixLabs.Security.Cryptography; + +public abstract partial class MerkleTree +{ + /// + /// Obtains a hash-only, non-generic from the current . + /// + /// Returns a hash-only, non-generic from the current . + public MerkleTree ToMerkleTree() + { + IEnumerable hashes = GetLeafHashes(); + return Create(hashes); + } + + /// + /// Obtains the leaf values from the current . + /// + /// Returns an containing the leaf values from the current . + public ImmutableList GetLeafValues() + { + ICollection result = EmptyList(); + CollectLeafValues(this, result); + return result.ToImmutableList(); + } + + /// + /// Recursively iterates through the specified to collect leaf hashes. + /// + /// The current from which to begin iterating through. + /// The collection that will contain the leaf hashes from the current . + protected override void CollectLeafHashes(MerkleTree current, ICollection items) + { + switch (current) + { + case MerkleTreeBranchNode branch: + CollectLeafHashes(branch.Left, items); + CollectLeafHashes(branch.Right, items); + break; + case MerkleTreeLeafNode leaf: + items.Add(leaf.Hash); + break; + } + } + + /// + /// Recursively iterates through the specified to collect leaf values. + /// + /// The current from which to begin iterating through. + /// The list that will contain the leaf values from the current . + private static void CollectLeafValues(MerkleTree current, ICollection items) + { + switch (current) + { + case MerkleTreeBranchNode branch: + CollectLeafValues(branch.Left, items); + CollectLeafValues(branch.Right, items); + break; + case MerkleTreeLeafNode leaf: + items.Add(leaf.Value); + break; + } + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs new file mode 100644 index 0000000..2021787 --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs @@ -0,0 +1,99 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Security.Cryptography; + +/// +/// Represents a generic Merkle tree. +/// +public abstract partial class MerkleTree : MerkleTree where T : IHashable +{ + /// + /// Represents a generic Merkle tree branch node. + /// + private sealed class MerkleTreeBranchNode : MerkleTree where THashable : IHashable + { + /// + /// Creates a new instance of the class. + /// + /// The left-hand node. + /// The right-hand node. + public MerkleTreeBranchNode(MerkleTree left, MerkleTree right) + { + Left = left; + Right = right; + Hash = Left.Hash.Concatenate(Right.Hash); + } + + /// + /// Gets the left-hand node. + /// + public MerkleTree Left { get; } + + /// + /// Gets the right-hand node. + /// + public MerkleTree Right { get; } + + /// + /// Gets the of the current node. + /// + public override Hash Hash { get; } + } + + /// + /// Represents a generic Merkle tree leaf node. + /// + private sealed class MerkleTreeLeafNode : MerkleTree where THashable : IHashable + { + /// + /// Creates a new instance of the class. + /// + /// The underlying value of the current node. + public MerkleTreeLeafNode(THashable value) + { + Value = value; + } + + /// + /// Gets the underlying value of the current node. + /// + public THashable Value { get; } + + /// + /// Gets the of the current node. + /// + public override Hash Hash => Value.ComputeHash(); + } + + /// + /// Represents an empty generic Merkle tree node. + /// + private sealed class MerkleTreeEmptyNode : MerkleTree where THashable : IHashable + { + /// + /// Creates a new instance of the class. + /// + /// The for the current node. + public MerkleTreeEmptyNode(HashAlgorithmType type) + { + Hash = Hash.CreateAllZeroHash(type); + } + + /// + /// Gets the of the current node. + /// + public override Hash Hash { get; } + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Get.cs b/OnixLabs.Security.Cryptography/MerkleTree.Get.cs new file mode 100644 index 0000000..be1e9bc --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.Get.cs @@ -0,0 +1,51 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace OnixLabs.Security.Cryptography; + +public abstract partial class MerkleTree +{ + /// + /// Obtains the leaf hashes from the current . + /// + /// Returns an containing the leaf hashes from the current . + public ImmutableList GetLeafHashes() + { + ICollection result = EmptyList(); + CollectLeafHashes(this, result); + return result.ToImmutableList(); + } + + /// + /// Recursively iterates through the specified to collect leaf hashes. + /// + /// The current from which to begin iterating through. + /// The list that will contain the leaf hashes from the current . + protected virtual void CollectLeafHashes(MerkleTree current, ICollection items) + { + switch (current) + { + case MerkleTreeBranchNode branch: + CollectLeafHashes(branch.Left, items); + CollectLeafHashes(branch.Right, items); + break; + case MerkleTreeLeafNode leaf: + items.Add(leaf.Hash); + break; + } + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.To.cs b/OnixLabs.Security.Cryptography/MerkleTree.To.cs new file mode 100644 index 0000000..9cd1dfb --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.To.cs @@ -0,0 +1,27 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Security.Cryptography; + +public abstract partial class MerkleTree +{ + /// + /// Returns a that represents the current object. + /// + /// A that represents the current object. + public sealed override string ToString() + { + return Hash.ToString(); + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.cs b/OnixLabs.Security.Cryptography/MerkleTree.cs index fca22af..1c07d0a 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,12 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using System.Collections.Generic; -using System.Linq; -using OnixLabs.Core.Linq; -using static OnixLabs.Core.Preconditions; - namespace OnixLabs.Security.Cryptography; /// @@ -33,106 +27,80 @@ internal MerkleTree() } /// - /// Gets the hash of this node. + /// Gets the of the current node. /// public abstract Hash Hash { get; } /// - /// Builds a Merkle tree from the specified leaf node hashes. + /// Represents a Merkle tree branch node. /// - /// The leaf nodes from which to build a Merkle tree. - /// Returns a new instance from the specified leaf nodes. - public static MerkleTree Build(IEnumerable nodes) + private sealed class MerkleTreeBranchNode : MerkleTree { - IReadOnlyList leafNodes = nodes.Select(MerkleTreeLeafNode.CreateHashNode).ToList(); - return Build(leafNodes); - } - - /// - /// Builds a Merkle tree from the specified Merkle tree nodes. - /// - /// The Merkle tree nodes from which to build a Merkle tree. - /// Returns a new instance from the specified nodes. - private static MerkleTree Build(IReadOnlyList nodes) - { - CheckIfMerkleTreesAreEmpty(nodes); - CheckNodesHaveEqualHashAlgorithms(nodes); + /// + /// Creates a new instance of the class. + /// + /// The left-hand node. + /// The right-hand node. + public MerkleTreeBranchNode(MerkleTree left, MerkleTree right) + { + Left = left; + Right = right; + Hash = Left.Hash.Concatenate(Right.Hash); + } - return MergeMerkleTreeNodes(nodes); - } + /// + /// Gets the left-hand node. + /// + public MerkleTree Left { get; } - /// - /// Checks whether an is empty. - /// - /// The to check. - /// if the is empty. - private static void CheckIfMerkleTreesAreEmpty(IEnumerable merkleTrees) - { - Check(merkleTrees.IsNotEmpty(), "Cannot construct a merkle tree from an empty list."); - } + /// + /// Gets the right-hand node. + /// + public MerkleTree Right { get; } - /// - /// Checks whether all elements of an have the same hash algorithm type. - /// - /// The to check. - /// if the elements of the do not have the same hash algorithm type. - private static void CheckNodesHaveEqualHashAlgorithms(IEnumerable merkleTrees) - { - Check(merkleTrees.AllEqualBy(merkleTree => merkleTree.Hash.AlgorithmType), - "Cannot construct a merkle tree with different hash types."); + /// + /// Gets the of the current node. + /// + public override Hash Hash { get; } } /// - /// Ensures that an has an even number of elements. - /// If the contains an odd number of elements, then an all-zero hash - /// of the same will be inserted at the end of the list. + /// Represents a Merkle tree leaf node. /// - /// The to ensure has an even number of elements. - /// Returns a new containing an even number of elements. - private static IReadOnlyList EnsureEvenNumberOfNodes(IReadOnlyList merkleTrees) + private sealed class MerkleTreeLeafNode : MerkleTree { - if (merkleTrees.IsCountEven()) return merkleTrees; + /// + /// Creates a new instance of the class. + /// + /// The value for the current node. + public MerkleTreeLeafNode(Hash hash) + { + Hash = hash; + } - HashAlgorithmType hashAlgorithmType = merkleTrees[0].Hash.AlgorithmType; - return merkleTrees.Append(MerkleTreeLeafNode.CreateEmptyNode(hashAlgorithmType)).ToList(); + /// + /// Gets the of the current node. + /// + public override Hash Hash { get; } } /// - /// Merges an of Merkle tree nodes. + /// Represents an empty Merkle tree node. /// - /// The of Merkle tree nodes to merge. - /// Returns a merged of Merkle tree nodes. - private static MerkleTree MergeMerkleTreeNodes(IReadOnlyList merkleTrees) + private sealed class MerkleTreeEmptyNode : MerkleTree { - while (true) + /// + /// Creates a new instance of the class. + /// + /// The for the current node. + public MerkleTreeEmptyNode(HashAlgorithmType type) { - if (merkleTrees.IsSingle()) - { - return merkleTrees[0]; - } - - merkleTrees = EnsureEvenNumberOfNodes(merkleTrees); - - List mutableMerkleTrees = new(); - - for (int index = 0; index < merkleTrees.Count; index += 2) - { - MerkleTree leftMerkleTree = merkleTrees[index]; - MerkleTree rightMerkleTree = merkleTrees[index + 1]; - MerkleTree merkleTreeNode = new MerkleTreeBranchNode(leftMerkleTree, rightMerkleTree); - mutableMerkleTrees.Add(merkleTreeNode); - } - - merkleTrees = mutableMerkleTrees; + Hash = Hash.CreateAllZeroHash(type); } - } - /// - /// Returns a that represents the current object. - /// - /// A that represents the current object. - public override string ToString() - { - return Hash.ToString(); + /// + /// Gets the of the current node. + /// + public override Hash Hash { get; } } } diff --git a/OnixLabs.Security.Cryptography/MerkleTreeBranchNode.cs b/OnixLabs.Security.Cryptography/MerkleTreeBranchNode.cs deleted file mode 100644 index 40dc405..0000000 --- a/OnixLabs.Security.Cryptography/MerkleTreeBranchNode.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020-2022 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Security.Cryptography; - -/// -/// Represents a Merkle tree branch node. -/// -internal sealed class MerkleTreeBranchNode : MerkleTree -{ - /// - /// Creates a new instance of the class. - /// - /// The left-hand node. - /// The right-hand node. - public MerkleTreeBranchNode(MerkleTree left, MerkleTree right) - { - Left = left; - Right = right; - } - - /// - /// Gets the left-hand node. - /// - public MerkleTree Left { get; } - - /// - /// Gets the right-hand node. - /// - public MerkleTree Right { get; } - - /// - /// Gets the hash of this node. - /// - public override Hash Hash => Left.Hash.Concatenate(Right.Hash); -} diff --git a/OnixLabs.Security.Cryptography/MerkleTreeLeafNode.cs b/OnixLabs.Security.Cryptography/MerkleTreeLeafNode.cs deleted file mode 100644 index d73f785..0000000 --- a/OnixLabs.Security.Cryptography/MerkleTreeLeafNode.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2020-2022 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Security.Cryptography; - -/// -/// Represents a Merkle tree leaf node. -/// -internal sealed class MerkleTreeLeafNode : MerkleTree -{ - /// - /// Creates a new instance of the class. - /// - public MerkleTreeLeafNode(Hash hash) - { - Hash = hash; - } - - /// - /// Gets the hash of this node. - /// - public override Hash Hash { get; } - - /// - /// Creates a from from the specified hash. - /// - /// The from which to create a node. - /// Returns an node. - public static MerkleTree CreateHashNode(Hash hash) - { - return new MerkleTreeLeafNode(hash); - } - - /// - /// Creates an empty node represented by an all-zero hash. - /// - /// The hash algorithm type of the node to create. - /// Returns an empty node represented by an all-zero hash. - public static MerkleTree CreateEmptyNode(HashAlgorithmType type) - { - return new MerkleTreeLeafNode(Hash.CreateAllZeroHash(type)); - } -} diff --git a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj index 0e2dc8b..11c7b18 100644 --- a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj +++ b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj @@ -1,31 +1,33 @@ - net6.0 + net7.0 OnixLabs.Security.Cryptography ONIXLabs ONIXLabs Cryptography API for .NET - 5.0.0 + 6.0.0 en enable true - Copyright © ONIXLabs 2020-2022 + Copyright © ONIXLabs 2020-2023 https://github.com/onix-labs/onixlabs-dotnet - 5.0.0 - 10 + 6.0.0 + 11 - bin\Debug\net5.0\OnixLabs.Security.Cryptography.xml + bin\Debug\net5.0\OnixLabs.Security.Cryptography.xml - bin\Release\net5.0\OnixLabs.Security.Cryptography.xml - true + bin\Release\net5.0\OnixLabs.Security.Cryptography.xml + true - + + + diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs b/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs index 10cfd17..e1ba46a 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,28 +20,6 @@ namespace OnixLabs.Security.Cryptography; public abstract partial class PrivateKey : IEquatable { - /// - /// Performs an equality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(PrivateKey a, PrivateKey b) - { - return Equals(a, b); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(PrivateKey a, PrivateKey b) - { - return !Equals(a, b); - } - /// /// Checks for equality between this instance and another object. /// @@ -74,4 +52,26 @@ public override int GetHashCode() { return HashCode.Combine(GetType(), AlgorithmType, KeyData.GetContentHashCode()); } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(PrivateKey left, PrivateKey right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(PrivateKey left, PrivateKey right) + { + return !Equals(left, right); + } } diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Export.cs b/OnixLabs.Security.Cryptography/PrivateKey.Export.cs index c09ebe6..44dc662 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Export.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Get.cs b/OnixLabs.Security.Cryptography/PrivateKey.Get.cs index 2c165e4..b9c6233 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs index 3caca47..fc0d80a 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.To.cs b/OnixLabs.Security.Cryptography/PrivateKey.To.cs index 8b72475..4366e39 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.To.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ public byte[] ToByteArray() /// Returns a value that represents the underlying private key data. public Base16 ToBase16() { - return Base16.FromByteArray(KeyData); + return Base16.Create(KeyData); } /// @@ -54,7 +54,7 @@ public Base32 ToBase32() /// Returns a value that represents the underlying private key data. public Base32 ToBase32(Base32Alphabet alphabet) { - return Base32.FromByteArray(KeyData, alphabet); + return Base32.Create(KeyData, alphabet); } /// @@ -73,7 +73,7 @@ public Base58 ToBase58() /// Returns a value that represents the underlying private key data. public Base58 ToBase58(Base58Alphabet alphabet) { - return Base58.FromByteArray(KeyData, alphabet); + return Base58.Create(KeyData, alphabet); } /// @@ -82,7 +82,7 @@ public Base58 ToBase58(Base58Alphabet alphabet) /// Returns a value that represents the underlying private key data. public Base64 ToBase64() { - return Base64.FromByteArray(KeyData); + return Base64.Create(KeyData); } /// diff --git a/OnixLabs.Security.Cryptography/PrivateKey.cs b/OnixLabs.Security.Cryptography/PrivateKey.cs index 5a74e98..8622dc0 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; + namespace OnixLabs.Security.Cryptography; /// @@ -27,8 +29,7 @@ public abstract partial class PrivateKey protected PrivateKey(byte[] data, HashAlgorithmType type) { type.GetHashAlgorithmName(); - - KeyData = data; + KeyData = data.Copy(); AlgorithmType = type; } diff --git a/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs b/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs index 66ef8d0..fc0a605 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -20,28 +20,6 @@ namespace OnixLabs.Security.Cryptography; public abstract partial class PublicKey : IEquatable { - /// - /// Performs an equality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(PublicKey a, PublicKey b) - { - return Equals(a, b); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(PublicKey a, PublicKey b) - { - return !Equals(a, b); - } - /// /// Checks for equality between this instance and another object. /// @@ -74,4 +52,26 @@ public override int GetHashCode() { return HashCode.Combine(GetType(), AlgorithmType, KeyData.GetContentHashCode()); } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(PublicKey left, PublicKey right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(PublicKey left, PublicKey right) + { + return !Equals(left, right); + } } diff --git a/OnixLabs.Security.Cryptography/PublicKey.To.cs b/OnixLabs.Security.Cryptography/PublicKey.To.cs index 1292aa1..48b5210 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.To.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ public byte[] ToByteArray() /// Returns a value that represents the underlying public key data. public Base16 ToBase16() { - return Base16.FromByteArray(KeyData); + return Base16.Create(KeyData); } /// @@ -54,7 +54,7 @@ public Base32 ToBase32() /// Returns a value that represents the underlying public key data. public Base32 ToBase32(Base32Alphabet alphabet) { - return Base32.FromByteArray(KeyData, alphabet); + return Base32.Create(KeyData, alphabet); } /// @@ -73,7 +73,7 @@ public Base58 ToBase58() /// Returns a value that represents the underlying public key data. public Base58 ToBase58(Base58Alphabet alphabet) { - return Base58.FromByteArray(KeyData, alphabet); + return Base58.Create(KeyData, alphabet); } /// @@ -82,7 +82,7 @@ public Base58 ToBase58(Base58Alphabet alphabet) /// Returns a value that represents the underlying public key data. public Base64 ToBase64() { - return Base64.FromByteArray(KeyData); + return Base64.Create(KeyData); } /// diff --git a/OnixLabs.Security.Cryptography/PublicKey.Verify.cs b/OnixLabs.Security.Cryptography/PublicKey.Verify.cs index f8e6e2c..11489c1 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PublicKey.cs b/OnixLabs.Security.Cryptography/PublicKey.cs index a763b4d..39872db 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; + namespace OnixLabs.Security.Cryptography; /// @@ -27,8 +29,7 @@ public abstract partial class PublicKey protected PublicKey(byte[] data, HashAlgorithmType type) { type.GetHashAlgorithmName(); - - KeyData = data; + KeyData = data.Copy(); AlgorithmType = type; } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.From.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs similarity index 82% rename from OnixLabs.Security.Cryptography/RsaPrivateKey.From.cs rename to OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs index f3e3317..c84e1de 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.From.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ public sealed partial class RsaPrivateKey /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey FromByteArray(byte[] key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPrivateKey Create(byte[] key, HashAlgorithmType type, RSASignaturePadding padding) { return new RsaPrivateKey(key, type, padding); } @@ -38,10 +38,10 @@ public static RsaPrivateKey FromByteArray(byte[] key, HashAlgorithmType type, RS /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey FromBase16(Base16 key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPrivateKey Create(Base16 key, HashAlgorithmType type, RSASignaturePadding padding) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } /// @@ -51,10 +51,10 @@ public static RsaPrivateKey FromBase16(Base16 key, HashAlgorithmType type, RSASi /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey FromBase32(Base32 key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPrivateKey Create(Base32 key, HashAlgorithmType type, RSASignaturePadding padding) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } /// @@ -64,10 +64,10 @@ public static RsaPrivateKey FromBase32(Base32 key, HashAlgorithmType type, RSASi /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey FromBase58(Base58 key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPrivateKey Create(Base58 key, HashAlgorithmType type, RSASignaturePadding padding) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } /// @@ -77,9 +77,9 @@ public static RsaPrivateKey FromBase58(Base58 key, HashAlgorithmType type, RSASi /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey FromBase64(Base64 key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPrivateKey Create(Base64 key, HashAlgorithmType type, RSASignaturePadding padding) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs index d4c66fe..a2df692 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs index 3acf64c..69f119d 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,9 +26,7 @@ public sealed partial class RsaPrivateKey public override byte[] ExportPkcs8Key() { using RSA privateKey = RSA.Create(); - privateKey.ImportRSAPrivateKey(KeyData, out int _); - return privateKey.ExportPkcs8PrivateKey(); } @@ -41,9 +39,7 @@ public override byte[] ExportPkcs8Key() public override byte[] ExportPkcs8Key(ReadOnlySpan password, PbeParameters parameters) { using RSA privateKey = RSA.Create(); - privateKey.ImportRSAPrivateKey(KeyData, out int _); - return privateKey.ExportEncryptedPkcs8PrivateKey(password, parameters); } } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs index a9e27cf..2d4f82c 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs index 7c1782b..aabf49e 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ public static RsaPrivateKey ImportPkcs8Key(ReadOnlySpan data, HashAlgorith privateKey.ImportPkcs8PrivateKey(data, out int _); byte[] bytes = privateKey.ExportRSAPrivateKey(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } /// @@ -68,7 +68,7 @@ public static RsaPrivateKey ImportPkcs8Key( privateKey.ImportEncryptedPkcs8PrivateKey(password, data, out int _); byte[] bytes = privateKey.ExportRSAPrivateKey(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } /// diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs index 5463d6d..4496ca3 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -31,7 +31,7 @@ public override DigitalSignature SignData(byte[] unsignedData) HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); byte[] signedData = privateKey.SignData(unsignedData, name, Padding); - return DigitalSignature.FromByteArray(signedData); + return DigitalSignature.Create(signedData); } /// @@ -47,6 +47,6 @@ public override DigitalSignature SignHash(byte[] unsignedHash) HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); byte[] signedData = privateKey.SignHash(unsignedHash, name, Padding); - return DigitalSignature.FromByteArray(signedData); + return DigitalSignature.Create(signedData); } } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.cs index 5d6d3e4..6de4643 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.From.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs similarity index 82% rename from OnixLabs.Security.Cryptography/RsaPublicKey.From.cs rename to OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs index b024572..898d221 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.From.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ public sealed partial class RsaPublicKey /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey FromByteArray(byte[] key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPublicKey Create(byte[] key, HashAlgorithmType type, RSASignaturePadding padding) { return new RsaPublicKey(key, type, padding); } @@ -38,10 +38,10 @@ public static RsaPublicKey FromByteArray(byte[] key, HashAlgorithmType type, RSA /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey FromBase16(Base16 key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPublicKey Create(Base16 key, HashAlgorithmType type, RSASignaturePadding padding) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } /// @@ -51,10 +51,10 @@ public static RsaPublicKey FromBase16(Base16 key, HashAlgorithmType type, RSASig /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey FromBase32(Base32 key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPublicKey Create(Base32 key, HashAlgorithmType type, RSASignaturePadding padding) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } /// @@ -64,10 +64,10 @@ public static RsaPublicKey FromBase32(Base32 key, HashAlgorithmType type, RSASig /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey FromBase58(Base58 key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPublicKey Create(Base58 key, HashAlgorithmType type, RSASignaturePadding padding) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } /// @@ -77,9 +77,9 @@ public static RsaPublicKey FromBase58(Base58 key, HashAlgorithmType type, RSASig /// The for computing signature data. /// The for computing signature data. /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey FromBase64(Base64 key, HashAlgorithmType type, RSASignaturePadding padding) + public static RsaPublicKey Create(Base64 key, HashAlgorithmType type, RSASignaturePadding padding) { byte[] bytes = key.ToByteArray(); - return FromByteArray(bytes, type, padding); + return Create(bytes, type, padding); } } diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs index 21fd875..772b9d3 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs index c71ea71..08205e9 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,11 +27,9 @@ public sealed partial class RsaPublicKey public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData) { using RSA publicKey = RSA.Create(); - publicKey.ImportRSAPublicKey(KeyData, out int _); byte[] signatureData = signature.ToByteArray(); HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - return publicKey.VerifyData(unsignedData, signatureData, name, Padding); } @@ -44,11 +42,9 @@ public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData public override bool IsHashValid(DigitalSignature signature, byte[] unsignedHash) { using RSA publicKey = RSA.Create(); - publicKey.ImportRSAPublicKey(KeyData, out int _); byte[] signatureData = signature.ToByteArray(); HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - return publicKey.VerifyHash(unsignedHash, signatureData, name, Padding); } } diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.cs index 1bcba28..8b8252e 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Salt.Create.cs b/OnixLabs.Security.Cryptography/Salt.Create.cs new file mode 100644 index 0000000..ddbb4fc --- /dev/null +++ b/OnixLabs.Security.Cryptography/Salt.Create.cs @@ -0,0 +1,56 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Security.Cryptography; + +namespace OnixLabs.Security.Cryptography; + +public readonly partial struct Salt +{ + /// + /// Creates a instance from a array. + /// + /// The array to represent as a salt. + /// A new instance. + public static Salt Create(byte[] value) + { + return new Salt(value); + } + + /// + /// Creates a of the specified length. + /// + /// The length of the salt to create. + /// Returns a new instance of the specified length. + public static Salt Create(int length) + { + using RandomNumberGenerator generator = RandomNumberGenerator.Create(); + byte[] value = new byte[length]; + generator.GetBytes(value); + return Create(value); + } + + /// + /// Creates a non-zero of the specified length. + /// + /// The length of the salt to create. + /// Returns a new non-zero instance of the specified length. + public static Salt CreateNonZero(int length) + { + using RandomNumberGenerator generator = RandomNumberGenerator.Create(); + byte[] value = new byte[length]; + generator.GetNonZeroBytes(value); + return Create(value); + } +} diff --git a/OnixLabs.Security.Cryptography/Salt.Equatable.cs b/OnixLabs.Security.Cryptography/Salt.Equatable.cs new file mode 100644 index 0000000..4d10020 --- /dev/null +++ b/OnixLabs.Security.Cryptography/Salt.Equatable.cs @@ -0,0 +1,73 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Linq; +using OnixLabs.Core.Linq; + +namespace OnixLabs.Security.Cryptography; + +public readonly partial struct Salt : IEquatable +{ + /// + /// Checks for equality between this instance and another object. + /// + /// The object to check for equality. + /// true if the object is equal to this instance; otherwise, false. + public bool Equals(Salt other) + { + return other.Value.SequenceEqual(Value); + } + + /// + /// Checks for equality between this instance and another object. + /// + /// The object to check for equality. + /// true if the object is equal to this instance; otherwise, false. + public override bool Equals(object? obj) + { + return obj is Salt other && Equals(other); + } + + /// + /// Serves as a hash code function for this instance. + /// + /// A hash code for this instance. + public override int GetHashCode() + { + return HashCode.Combine(Value.GetContentHashCode()); + } + + /// + /// Performs an equality check between two object instances. + /// + /// Instance a. + /// Instance b. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(Salt left, Salt right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// Instance a. + /// Instance b. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(Salt left, Salt right) + { + return !Equals(left, right); + } +} diff --git a/OnixLabs.Security.Cryptography/Salt.To.cs b/OnixLabs.Security.Cryptography/Salt.To.cs new file mode 100644 index 0000000..fad7cdb --- /dev/null +++ b/OnixLabs.Security.Cryptography/Salt.To.cs @@ -0,0 +1,60 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Core; +using OnixLabs.Core.Text; + +namespace OnixLabs.Security.Cryptography; + +public readonly partial struct Salt +{ + /// + /// Returns a array containing the underlying salt data. + /// + /// A array containing the underlying salt data. + public byte[] ToByteArray() + { + return Value.Copy(); + } + + /// + /// Creates a from the current salt data. + /// + /// The of the hash to produce. + /// Returns a of the current salt data. + public Hash ToHash(HashAlgorithmType type) + { + return Hash.ComputeHash(Value, type); + } + + /// + /// Creates a from the current salt data. + /// + /// The of the hash to produce. + /// The length of the hash to produce. + /// Returns a of the current salt data. + public Hash ToHash(HashAlgorithmType type, int length) + { + return Hash.ComputeHash(Value, type, length); + } + + /// + /// Returns a that represents the current object. + /// + /// A that represents the current object. + public override string ToString() + { + return Base16.Create(Value).ToString(); + } +} diff --git a/OnixLabs.Security.Cryptography/Salt.cs b/OnixLabs.Security.Cryptography/Salt.cs new file mode 100644 index 0000000..cfac012 --- /dev/null +++ b/OnixLabs.Security.Cryptography/Salt.cs @@ -0,0 +1,37 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography; + +/// +/// Represents a cryptographically secure random value. +/// +public readonly partial struct Salt +{ + /// + /// Initializes a new instance of the struct. + /// + /// The underlying cryptographically secure random value. + private Salt(byte[] value) + { + Value = value.Copy(); + } + + /// + /// Gets the underlying cryptographically secure random value. + /// + private byte[] Value { get; } +} diff --git a/OnixLabs.Security.Cryptography/Sha3.Create.cs b/OnixLabs.Security.Cryptography/Sha3.Create.cs index d10375c..84ab6fa 100644 --- a/OnixLabs.Security.Cryptography/Sha3.Create.cs +++ b/OnixLabs.Security.Cryptography/Sha3.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3.Permute.cs b/OnixLabs.Security.Cryptography/Sha3.Permute.cs index 948cf03..001b979 100644 --- a/OnixLabs.Security.Cryptography/Sha3.Permute.cs +++ b/OnixLabs.Security.Cryptography/Sha3.Permute.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3.cs b/OnixLabs.Security.Cryptography/Sha3.cs index 34f8a7f..2319244 100644 --- a/OnixLabs.Security.Cryptography/Sha3.cs +++ b/OnixLabs.Security.Cryptography/Sha3.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -113,8 +113,8 @@ protected override void HashCore(byte[] array, int ibStart, int cbSize) for (int index = ibStart; index < blockSize; index++) { - byte x = Convert.ToByte(Buffer.GetByte(state, index) ^ array[index + inputPointer]); - Buffer.SetByte(state, index, x); + byte value = Convert.ToByte(Buffer.GetByte(state, index) ^ array[index + inputPointer]); + Buffer.SetByte(state, index, value); } inputPointer += blockSize; @@ -135,7 +135,7 @@ protected override byte[] HashFinal() byte pad = Convert.ToByte(Buffer.GetByte(state, blockSize) ^ delimiter); Buffer.SetByte(state, blockSize, pad); - if (((delimiter & 0x80) != 0) && blockSize == (rateBytes - 1)) + if ((delimiter & 0x80) != 0 && blockSize == rateBytes - 1) { Permute(state); } diff --git a/OnixLabs.Security.Cryptography/Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Sha3Hash224.cs index a2a375e..d50e78e 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash224.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash224.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Sha3Hash256.cs index c81f188..d589da2 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash256.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Sha3Hash384.cs index 373d70d..037166e 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash384.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Sha3Hash512.cs index 528e9a1..1249222 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash512.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Sha3Shake128.cs index ca3e692..470591b 100644 --- a/OnixLabs.Security.Cryptography/Sha3Shake128.cs +++ b/OnixLabs.Security.Cryptography/Sha3Shake128.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Sha3Shake256.cs index fb82f5c..b13343b 100644 --- a/OnixLabs.Security.Cryptography/Sha3Shake256.cs +++ b/OnixLabs.Security.Cryptography/Sha3Shake256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2022 ONIXLabs +// Copyright 2020-2023 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/onixlabs-dotnet.sln b/onixlabs-dotnet.sln index c2af2ab..60962fd 100644 --- a/onixlabs-dotnet.sln +++ b/onixlabs-dotnet.sln @@ -16,6 +16,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Security.Cryptogra EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Security.Cryptography.UnitTests", "OnixLabs.Security.Cryptography.UnitTests\OnixLabs.Security.Cryptography.UnitTests.csproj", "{C3DE665B-5B02-41DE-8BB0-C53A1326E162}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Core.UnitTests.Data", "OnixLabs.Core.UnitTests.Data\OnixLabs.Core.UnitTests.Data.csproj", "{E3FBC79F-7F5A-4ECF-9653-C0AB203FF5D5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Security.Cryptography.UnitTests.Data", "OnixLabs.Security.Cryptography.UnitTests.Data\OnixLabs.Security.Cryptography.UnitTests.Data.csproj", "{513CFC09-42E2-43C3-BB68-90640D78CDF4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTestData", "UnitTestData", "{5BA28E51-3E67-4081-BD69-5AE6885C8F2A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +33,9 @@ Global {893547DB-4EAA-4D1F-886F-0D6114F8601E} = {C1D7FFDA-A234-4A01-9371-19C68DD74C91} {78FDB1BA-6545-41DE-99B8-F007C6A6B093} = {6E4FE7B0-5E44-4EB4-B64F-228645C4F79B} {C3DE665B-5B02-41DE-8BB0-C53A1326E162} = {C1D7FFDA-A234-4A01-9371-19C68DD74C91} + {5BA28E51-3E67-4081-BD69-5AE6885C8F2A} = {C1D7FFDA-A234-4A01-9371-19C68DD74C91} + {E3FBC79F-7F5A-4ECF-9653-C0AB203FF5D5} = {5BA28E51-3E67-4081-BD69-5AE6885C8F2A} + {513CFC09-42E2-43C3-BB68-90640D78CDF4} = {5BA28E51-3E67-4081-BD69-5AE6885C8F2A} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {1EDC1164-0205-433D-A356-00DAD4686264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -49,5 +58,13 @@ Global {C3DE665B-5B02-41DE-8BB0-C53A1326E162}.Debug|Any CPU.Build.0 = Debug|Any CPU {C3DE665B-5B02-41DE-8BB0-C53A1326E162}.Release|Any CPU.ActiveCfg = Release|Any CPU {C3DE665B-5B02-41DE-8BB0-C53A1326E162}.Release|Any CPU.Build.0 = Release|Any CPU + {E3FBC79F-7F5A-4ECF-9653-C0AB203FF5D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E3FBC79F-7F5A-4ECF-9653-C0AB203FF5D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E3FBC79F-7F5A-4ECF-9653-C0AB203FF5D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E3FBC79F-7F5A-4ECF-9653-C0AB203FF5D5}.Release|Any CPU.Build.0 = Release|Any CPU + {513CFC09-42E2-43C3-BB68-90640D78CDF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {513CFC09-42E2-43C3-BB68-90640D78CDF4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {513CFC09-42E2-43C3-BB68-90640D78CDF4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {513CFC09-42E2-43C3-BB68-90640D78CDF4}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/onixlabs-dotnet.sln.DotSettings b/onixlabs-dotnet.sln.DotSettings new file mode 100644 index 0000000..ba6a0f8 --- /dev/null +++ b/onixlabs-dotnet.sln.DotSettings @@ -0,0 +1,70 @@ + + Copyright 2020-$CURRENT_YEAR$ ONIXLabs + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True + True \ No newline at end of file From d1f0b3e153d012b3114300f48678084a9d85ea68 Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Tue, 17 Oct 2023 07:10:52 +0100 Subject: [PATCH 02/14] Better support for nuget (#26) --- OnixLabs.Core/OnixLabs.Core.csproj | 32 +++++++++++++++---- .../OnixLabs.Security.Cryptography.csproj | 31 +++++++++++++++--- 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj index b20b35e..fe902d5 100644 --- a/OnixLabs.Core/OnixLabs.Core.csproj +++ b/OnixLabs.Core/OnixLabs.Core.csproj @@ -15,16 +15,36 @@ 6.0.0 - - true - bin\Debug\net5.0\OnixLabs.Core.xml + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + embedded + true + true + true + Apache-2.0 + https://github.com/onix-labs/onixlabs-dotnet + README.md + true + true + git + https://github.com/onix-labs/onixlabs-dotnet - - bin\Release\net5.0\OnixLabs.Core.xml - true + + true + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + diff --git a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj index 11c7b18..1abfdb3 100644 --- a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj +++ b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj @@ -15,15 +15,36 @@ 11 - - bin\Debug\net5.0\OnixLabs.Security.Cryptography.xml + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + embedded + true + true + true + Apache-2.0 + https://github.com/onix-labs/onixlabs-dotnet + README.md + true + true + git + https://github.com/onix-labs/onixlabs-dotnet - - bin\Release\net5.0\OnixLabs.Security.Cryptography.xml - true + + true + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + From 5874ffbf387f3f82c394abae53a1ce36f9a76076 Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Sun, 22 Oct 2023 17:02:37 +0100 Subject: [PATCH 03/14] License text update (#28) --- OnixLabs.Core.UnitTests.Data/Objects/Color.cs | 2 +- OnixLabs.Core.UnitTests.Data/Objects/Element.cs | 2 +- OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs | 2 +- OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs | 2 +- OnixLabs.Core.UnitTests/ArrayExtensionTests.cs | 2 +- OnixLabs.Core.UnitTests/Collections/CollectionTests.cs | 2 +- OnixLabs.Core.UnitTests/EnumerationTests.cs | 2 +- OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs | 2 +- OnixLabs.Core.UnitTests/ObjectExtensionTests.cs | 2 +- OnixLabs.Core.UnitTests/PreconditionTests.cs | 2 +- OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs | 2 +- OnixLabs.Core.UnitTests/StringExtensionTests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base16Tests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs | 2 +- OnixLabs.Core.UnitTests/Text/Base64Tests.cs | 2 +- OnixLabs.Core/Collections/Collection.Empty.cs | 2 +- OnixLabs.Core/Collections/Collection.Of.cs | 2 +- OnixLabs.Core/Enumeration.Comparable.cs | 2 +- OnixLabs.Core/Enumeration.Equatable.cs | 2 +- OnixLabs.Core/Enumeration.From.cs | 2 +- OnixLabs.Core/Enumeration.Get.cs | 2 +- OnixLabs.Core/Enumeration.To.cs | 2 +- OnixLabs.Core/Enumeration.cs | 2 +- OnixLabs.Core/Extensions.Array.cs | 2 +- OnixLabs.Core/Extensions.Object.cs | 2 +- OnixLabs.Core/Extensions.String.cs | 2 +- OnixLabs.Core/Linq/Extensions.IEnumerable.cs | 2 +- OnixLabs.Core/Preconditions.cs | 2 +- OnixLabs.Core/Reflection/Extensions.Type.cs | 2 +- OnixLabs.Core/Text/Base16.Constants.cs | 2 +- OnixLabs.Core/Text/Base16.Create.cs | 2 +- OnixLabs.Core/Text/Base16.Equatable.cs | 2 +- OnixLabs.Core/Text/Base16.Parse.cs | 2 +- OnixLabs.Core/Text/Base16.To.cs | 2 +- OnixLabs.Core/Text/Base16.cs | 2 +- OnixLabs.Core/Text/Base32.Codec.cs | 2 +- OnixLabs.Core/Text/Base32.Constants.cs | 2 +- OnixLabs.Core/Text/Base32.Create.cs | 2 +- OnixLabs.Core/Text/Base32.Equatable.cs | 2 +- OnixLabs.Core/Text/Base32.Parse.cs | 2 +- OnixLabs.Core/Text/Base32.To.cs | 2 +- OnixLabs.Core/Text/Base32.cs | 2 +- OnixLabs.Core/Text/Base32Alphabet.cs | 2 +- OnixLabs.Core/Text/Base58.Checksum.cs | 2 +- OnixLabs.Core/Text/Base58.Codec.cs | 2 +- OnixLabs.Core/Text/Base58.Constants.cs | 2 +- OnixLabs.Core/Text/Base58.Create.cs | 2 +- OnixLabs.Core/Text/Base58.Equatable.cs | 2 +- OnixLabs.Core/Text/Base58.Parse.cs | 2 +- OnixLabs.Core/Text/Base58.To.cs | 2 +- OnixLabs.Core/Text/Base58.cs | 2 +- OnixLabs.Core/Text/Base58Alphabet.cs | 2 +- OnixLabs.Core/Text/Base64.Constants.cs | 2 +- OnixLabs.Core/Text/Base64.Create.cs | 2 +- OnixLabs.Core/Text/Base64.Equatable.cs | 2 +- OnixLabs.Core/Text/Base64.Parse.cs | 2 +- OnixLabs.Core/Text/Base64.To.cs | 2 +- OnixLabs.Core/Text/Base64.cs | 2 +- OnixLabs.Core/Text/IBase.cs | 2 +- OnixLabs.Playground/Program.cs | 2 +- .../Objects/MerkleNode.cs | 2 +- .../EcdsaEncryptedPkcs8Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/HashTests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs | 2 +- .../MerkleTreeGenericTests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs | 2 +- .../RsaKeyEncryptedPkcs8Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs | 2 +- OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs | 2 +- OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs | 2 +- OnixLabs.Security.Cryptography/DigitalSignature.Create.cs | 2 +- OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/DigitalSignature.To.cs | 2 +- OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs | 2 +- OnixLabs.Security.Cryptography/DigitalSignature.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs | 2 +- OnixLabs.Security.Cryptography/EcdsaPublicKey.cs | 2 +- OnixLabs.Security.Cryptography/Hash.AllOneHash.cs | 2 +- OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Compute.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs | 2 +- .../Hash.ComputeAsync.Sha3Shake128.cs | 2 +- .../Hash.ComputeAsync.Sha3Shake256.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs | 2 +- OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Concantenate.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Constants.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Create.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/Hash.Parse.cs | 2 +- OnixLabs.Security.Cryptography/Hash.To.cs | 2 +- OnixLabs.Security.Cryptography/Hash.cs | 2 +- .../HashAlgorithmType.Enumerations.cs | 2 +- OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs | 2 +- OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs | 2 +- OnixLabs.Security.Cryptography/HashAlgorithmType.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Compute.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Constants.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Create.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Parse.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.To.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.Verify.cs | 2 +- OnixLabs.Security.Cryptography/Hmac.cs | 2 +- OnixLabs.Security.Cryptography/IHashable.cs | 2 +- OnixLabs.Security.Cryptography/KeyPair.Create.cs | 2 +- OnixLabs.Security.Cryptography/KeyPair.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/KeyPair.From.cs | 2 +- OnixLabs.Security.Cryptography/KeyPair.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.Build.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.Generic.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.Get.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.To.cs | 2 +- OnixLabs.Security.Cryptography/MerkleTree.cs | 2 +- OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/PrivateKey.Export.cs | 2 +- OnixLabs.Security.Cryptography/PrivateKey.Get.cs | 2 +- OnixLabs.Security.Cryptography/PrivateKey.Sign.cs | 2 +- OnixLabs.Security.Cryptography/PrivateKey.To.cs | 2 +- OnixLabs.Security.Cryptography/PrivateKey.cs | 2 +- OnixLabs.Security.Cryptography/PublicKey.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/PublicKey.To.cs | 2 +- OnixLabs.Security.Cryptography/PublicKey.Verify.cs | 2 +- OnixLabs.Security.Cryptography/PublicKey.cs | 2 +- OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs | 2 +- OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs | 2 +- OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs | 2 +- OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs | 2 +- OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs | 2 +- OnixLabs.Security.Cryptography/RsaPrivateKey.cs | 2 +- OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs | 2 +- OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs | 2 +- OnixLabs.Security.Cryptography/RsaPublicKey.cs | 2 +- OnixLabs.Security.Cryptography/Salt.Create.cs | 2 +- OnixLabs.Security.Cryptography/Salt.Equatable.cs | 2 +- OnixLabs.Security.Cryptography/Salt.To.cs | 2 +- OnixLabs.Security.Cryptography/Salt.cs | 2 +- OnixLabs.Security.Cryptography/Sha3.Create.cs | 2 +- OnixLabs.Security.Cryptography/Sha3.Permute.cs | 2 +- OnixLabs.Security.Cryptography/Sha3.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Hash224.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Hash256.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Hash384.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Hash512.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Shake128.cs | 2 +- OnixLabs.Security.Cryptography/Sha3Shake256.cs | 2 +- onixlabs-dotnet.sln.DotSettings | 1 + 211 files changed, 211 insertions(+), 210 deletions(-) diff --git a/OnixLabs.Core.UnitTests.Data/Objects/Color.cs b/OnixLabs.Core.UnitTests.Data/Objects/Color.cs index 021ab6b..a254097 100644 --- a/OnixLabs.Core.UnitTests.Data/Objects/Color.cs +++ b/OnixLabs.Core.UnitTests.Data/Objects/Color.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests.Data/Objects/Element.cs b/OnixLabs.Core.UnitTests.Data/Objects/Element.cs index 38b3121..640b6c9 100644 --- a/OnixLabs.Core.UnitTests.Data/Objects/Element.cs +++ b/OnixLabs.Core.UnitTests.Data/Objects/Element.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs b/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs index 41300ce..496f6b6 100644 --- a/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs +++ b/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs b/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs index 1fcfe81..8d95ff4 100644 --- a/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs +++ b/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs b/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs index f2026e2..32407cf 100644 --- a/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs index 7d33dd7..5627a80 100644 --- a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs +++ b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/EnumerationTests.cs b/OnixLabs.Core.UnitTests/EnumerationTests.cs index 0799b72..cc6e166 100644 --- a/OnixLabs.Core.UnitTests/EnumerationTests.cs +++ b/OnixLabs.Core.UnitTests/EnumerationTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs index 466bdba..e23f23a 100644 --- a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs b/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs index c5583a1..25e5e3e 100644 --- a/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/PreconditionTests.cs b/OnixLabs.Core.UnitTests/PreconditionTests.cs index f5ff49d..b724d33 100644 --- a/OnixLabs.Core.UnitTests/PreconditionTests.cs +++ b/OnixLabs.Core.UnitTests/PreconditionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs b/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs index 012d861..c08ae92 100644 --- a/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/StringExtensionTests.cs b/OnixLabs.Core.UnitTests/StringExtensionTests.cs index 5e0057c..0e6445e 100644 --- a/OnixLabs.Core.UnitTests/StringExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/StringExtensionTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base16Tests.cs b/OnixLabs.Core.UnitTests/Text/Base16Tests.cs index 1e973bd..1ec84cb 100644 --- a/OnixLabs.Core.UnitTests/Text/Base16Tests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base16Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs index ce5bc0b..f4f5dab 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs index b63345b..5981312 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs index b976013..ba75917 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs index 9efc9da..9b4a129 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs index 5436846..6cd71fd 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs index a2c649c..50ee0aa 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs index a0fa2d6..b5b35ae 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests/Text/Base64Tests.cs b/OnixLabs.Core.UnitTests/Text/Base64Tests.cs index e75114c..2eca15a 100644 --- a/OnixLabs.Core.UnitTests/Text/Base64Tests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base64Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Collections/Collection.Empty.cs b/OnixLabs.Core/Collections/Collection.Empty.cs index 7c1fede..b77d2cc 100644 --- a/OnixLabs.Core/Collections/Collection.Empty.cs +++ b/OnixLabs.Core/Collections/Collection.Empty.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Collections/Collection.Of.cs b/OnixLabs.Core/Collections/Collection.Of.cs index cde7d88..3e7a095 100644 --- a/OnixLabs.Core/Collections/Collection.Of.cs +++ b/OnixLabs.Core/Collections/Collection.Of.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Enumeration.Comparable.cs b/OnixLabs.Core/Enumeration.Comparable.cs index 99aa808..03a988d 100644 --- a/OnixLabs.Core/Enumeration.Comparable.cs +++ b/OnixLabs.Core/Enumeration.Comparable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Enumeration.Equatable.cs b/OnixLabs.Core/Enumeration.Equatable.cs index f03cdb4..4efb291 100644 --- a/OnixLabs.Core/Enumeration.Equatable.cs +++ b/OnixLabs.Core/Enumeration.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Enumeration.From.cs b/OnixLabs.Core/Enumeration.From.cs index 959b92b..7846f24 100644 --- a/OnixLabs.Core/Enumeration.From.cs +++ b/OnixLabs.Core/Enumeration.From.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Enumeration.Get.cs b/OnixLabs.Core/Enumeration.Get.cs index 273f9df..68ae378 100644 --- a/OnixLabs.Core/Enumeration.Get.cs +++ b/OnixLabs.Core/Enumeration.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Enumeration.To.cs b/OnixLabs.Core/Enumeration.To.cs index 9e46dad..3eed646 100644 --- a/OnixLabs.Core/Enumeration.To.cs +++ b/OnixLabs.Core/Enumeration.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Enumeration.cs b/OnixLabs.Core/Enumeration.cs index 40c6230..aea73d2 100644 --- a/OnixLabs.Core/Enumeration.cs +++ b/OnixLabs.Core/Enumeration.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Extensions.Array.cs b/OnixLabs.Core/Extensions.Array.cs index 5900e62..c78835d 100644 --- a/OnixLabs.Core/Extensions.Array.cs +++ b/OnixLabs.Core/Extensions.Array.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Extensions.Object.cs b/OnixLabs.Core/Extensions.Object.cs index 728084a..67214fb 100644 --- a/OnixLabs.Core/Extensions.Object.cs +++ b/OnixLabs.Core/Extensions.Object.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Extensions.String.cs b/OnixLabs.Core/Extensions.String.cs index d2db538..387de23 100644 --- a/OnixLabs.Core/Extensions.String.cs +++ b/OnixLabs.Core/Extensions.String.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs index 240f409..540ef8d 100644 --- a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs +++ b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Preconditions.cs b/OnixLabs.Core/Preconditions.cs index c9295c4..f217b43 100644 --- a/OnixLabs.Core/Preconditions.cs +++ b/OnixLabs.Core/Preconditions.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Reflection/Extensions.Type.cs b/OnixLabs.Core/Reflection/Extensions.Type.cs index 9a26dd6..45cb1d1 100644 --- a/OnixLabs.Core/Reflection/Extensions.Type.cs +++ b/OnixLabs.Core/Reflection/Extensions.Type.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base16.Constants.cs b/OnixLabs.Core/Text/Base16.Constants.cs index 181b936..43a2705 100644 --- a/OnixLabs.Core/Text/Base16.Constants.cs +++ b/OnixLabs.Core/Text/Base16.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base16.Create.cs b/OnixLabs.Core/Text/Base16.Create.cs index 3a5dbb6..e9edc77 100644 --- a/OnixLabs.Core/Text/Base16.Create.cs +++ b/OnixLabs.Core/Text/Base16.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base16.Equatable.cs b/OnixLabs.Core/Text/Base16.Equatable.cs index 06509a2..1068f0e 100644 --- a/OnixLabs.Core/Text/Base16.Equatable.cs +++ b/OnixLabs.Core/Text/Base16.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base16.Parse.cs b/OnixLabs.Core/Text/Base16.Parse.cs index 7df68a0..216b40a 100644 --- a/OnixLabs.Core/Text/Base16.Parse.cs +++ b/OnixLabs.Core/Text/Base16.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base16.To.cs b/OnixLabs.Core/Text/Base16.To.cs index 1451088..464c2bd 100644 --- a/OnixLabs.Core/Text/Base16.To.cs +++ b/OnixLabs.Core/Text/Base16.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base16.cs b/OnixLabs.Core/Text/Base16.cs index 459c558..80373ff 100644 --- a/OnixLabs.Core/Text/Base16.cs +++ b/OnixLabs.Core/Text/Base16.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.Codec.cs b/OnixLabs.Core/Text/Base32.Codec.cs index 0923f48..b8747e0 100644 --- a/OnixLabs.Core/Text/Base32.Codec.cs +++ b/OnixLabs.Core/Text/Base32.Codec.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.Constants.cs b/OnixLabs.Core/Text/Base32.Constants.cs index 36fcda5..b0bfc27 100644 --- a/OnixLabs.Core/Text/Base32.Constants.cs +++ b/OnixLabs.Core/Text/Base32.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.Create.cs b/OnixLabs.Core/Text/Base32.Create.cs index e0c7cb3..2892bcb 100644 --- a/OnixLabs.Core/Text/Base32.Create.cs +++ b/OnixLabs.Core/Text/Base32.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.Equatable.cs b/OnixLabs.Core/Text/Base32.Equatable.cs index 2110ab5..31c4bf0 100644 --- a/OnixLabs.Core/Text/Base32.Equatable.cs +++ b/OnixLabs.Core/Text/Base32.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.Parse.cs b/OnixLabs.Core/Text/Base32.Parse.cs index 32c47d3..37acd54 100644 --- a/OnixLabs.Core/Text/Base32.Parse.cs +++ b/OnixLabs.Core/Text/Base32.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.To.cs b/OnixLabs.Core/Text/Base32.To.cs index 25a7ee4..44f1526 100644 --- a/OnixLabs.Core/Text/Base32.To.cs +++ b/OnixLabs.Core/Text/Base32.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.cs b/OnixLabs.Core/Text/Base32.cs index d26150f..597f022 100644 --- a/OnixLabs.Core/Text/Base32.cs +++ b/OnixLabs.Core/Text/Base32.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32Alphabet.cs b/OnixLabs.Core/Text/Base32Alphabet.cs index 07bc9b6..6ea1ebd 100644 --- a/OnixLabs.Core/Text/Base32Alphabet.cs +++ b/OnixLabs.Core/Text/Base32Alphabet.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.Checksum.cs b/OnixLabs.Core/Text/Base58.Checksum.cs index 9962a13..1529de9 100644 --- a/OnixLabs.Core/Text/Base58.Checksum.cs +++ b/OnixLabs.Core/Text/Base58.Checksum.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.Codec.cs b/OnixLabs.Core/Text/Base58.Codec.cs index f3fe9a7..a7ecea7 100644 --- a/OnixLabs.Core/Text/Base58.Codec.cs +++ b/OnixLabs.Core/Text/Base58.Codec.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.Constants.cs b/OnixLabs.Core/Text/Base58.Constants.cs index ded5b32..dc7e12e 100644 --- a/OnixLabs.Core/Text/Base58.Constants.cs +++ b/OnixLabs.Core/Text/Base58.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.Create.cs b/OnixLabs.Core/Text/Base58.Create.cs index 1e28dd3..3d18ed1 100644 --- a/OnixLabs.Core/Text/Base58.Create.cs +++ b/OnixLabs.Core/Text/Base58.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.Equatable.cs b/OnixLabs.Core/Text/Base58.Equatable.cs index b01f2b8..f327c23 100644 --- a/OnixLabs.Core/Text/Base58.Equatable.cs +++ b/OnixLabs.Core/Text/Base58.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.Parse.cs b/OnixLabs.Core/Text/Base58.Parse.cs index 6cbb20d..3044555 100644 --- a/OnixLabs.Core/Text/Base58.Parse.cs +++ b/OnixLabs.Core/Text/Base58.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.To.cs b/OnixLabs.Core/Text/Base58.To.cs index c175678..7add2f8 100644 --- a/OnixLabs.Core/Text/Base58.To.cs +++ b/OnixLabs.Core/Text/Base58.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.cs b/OnixLabs.Core/Text/Base58.cs index 6601b04..f01c1f3 100644 --- a/OnixLabs.Core/Text/Base58.cs +++ b/OnixLabs.Core/Text/Base58.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58Alphabet.cs b/OnixLabs.Core/Text/Base58Alphabet.cs index e0b608e..290f278 100644 --- a/OnixLabs.Core/Text/Base58Alphabet.cs +++ b/OnixLabs.Core/Text/Base58Alphabet.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base64.Constants.cs b/OnixLabs.Core/Text/Base64.Constants.cs index 42f665a..a44b4c1 100644 --- a/OnixLabs.Core/Text/Base64.Constants.cs +++ b/OnixLabs.Core/Text/Base64.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base64.Create.cs b/OnixLabs.Core/Text/Base64.Create.cs index cc1e893..3e605f1 100644 --- a/OnixLabs.Core/Text/Base64.Create.cs +++ b/OnixLabs.Core/Text/Base64.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base64.Equatable.cs b/OnixLabs.Core/Text/Base64.Equatable.cs index c20dd40..cfedb91 100644 --- a/OnixLabs.Core/Text/Base64.Equatable.cs +++ b/OnixLabs.Core/Text/Base64.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base64.Parse.cs b/OnixLabs.Core/Text/Base64.Parse.cs index 30d5656..10c1512 100644 --- a/OnixLabs.Core/Text/Base64.Parse.cs +++ b/OnixLabs.Core/Text/Base64.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base64.To.cs b/OnixLabs.Core/Text/Base64.To.cs index b1bf57c..2386b73 100644 --- a/OnixLabs.Core/Text/Base64.To.cs +++ b/OnixLabs.Core/Text/Base64.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base64.cs b/OnixLabs.Core/Text/Base64.cs index bb44ee5..0bb0960 100644 --- a/OnixLabs.Core/Text/Base64.cs +++ b/OnixLabs.Core/Text/Base64.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/IBase.cs b/OnixLabs.Core/Text/IBase.cs index 942607d..62a6336 100644 --- a/OnixLabs.Core/Text/IBase.cs +++ b/OnixLabs.Core/Text/IBase.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Playground/Program.cs b/OnixLabs.Playground/Program.cs index 6928888..d7c13e1 100644 --- a/OnixLabs.Playground/Program.cs +++ b/OnixLabs.Playground/Program.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs b/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs index 8910d38..00f6ecd 100644 --- a/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs index 51ab09c..6e218c7 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs index df56126..89b91b5 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs index b0af0f8..07f7098 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs index 2727b78..c06e6ff 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs index 458a36e..7c01726 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs index 289f306..d113d43 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs index 98206c4..03df0f0 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs index 0fec088..6607122 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs index 2fab50a..bad2f1b 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs index e62d418..36cb609 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs index 2a8465f..858cc8f 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs index 39893b5..86f9e4d 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs index 0dd6201..284ba01 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs b/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs index 59ba584..f900e5b 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs index 733421f..e659206 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs index a72ec1f..bd7044e 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs index f80bfdb..dd41f1b 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs index 1cead0f..ee6545c 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs index 954e92e..3bef195 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs index 8ef351c..c958b84 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs index 75bd24e..82e0a05 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs index 0f786d2..968fffc 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs index b6f137c..2755a50 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs index 7029f35..c7710f8 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs index b1585fe..b3bb450 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs index 8bab643..a993c91 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs index b7b3956..d743eff 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.cs b/OnixLabs.Security.Cryptography/DigitalSignature.cs index ad3abbb..d44a6b7 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs index fb6117a..931b937 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs index cadf8d1..53f8083 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs index e5299ae..6a4c06e 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs index fe313b6..6ffa465 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs index 9fef639..3562fac 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs index 67f2cac..2a9d4e3 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs index 9f08b21..8aeee19 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs index 2fb025d..51b7527 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs index 9fe126c..d372145 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs b/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs index 257a47b..ab198ee 100644 --- a/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs +++ b/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs b/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs index c620bce..6063f12 100644 --- a/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs +++ b/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs index 99d1df4..4124d5a 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs index 7e7a644..75afcec 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs index 323b418..ec0372e 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs index f219c2f..3e9660f 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs index a2fb9f3..c50f5b1 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs index ed9d218..5cb6b18 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs index d96126e..691c709 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs index e32133a..72f1170 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs index c3785c9..ed9b710 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs index ff62fd8..32d9895 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs index 5005481..60e8561 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.cs b/OnixLabs.Security.Cryptography/Hash.Compute.cs index d861f01..773cd8a 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs index ed6d011..2bddadd 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs index 14e092d..5adbaff 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs index 7b3afb7..8d20153 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs index 7f32ee7..2ca6731 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs index fdc32a7..fd78293 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs index 9a2784b..34c8cba 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs index d2991ba..0c8e6f0 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs index 0084c4c..b91538e 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs index 5e459b1..f6f0bf9 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs index 5ad5063..aa62839 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs index 0c6346e..d1154b7 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs index 926e239..5855f09 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs b/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs index 27c88d0..1ae41ad 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs b/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs index 983f8d3..bd727e5 100644 --- a/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs +++ b/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Concantenate.cs b/OnixLabs.Security.Cryptography/Hash.Concantenate.cs index d1e21f9..3027936 100644 --- a/OnixLabs.Security.Cryptography/Hash.Concantenate.cs +++ b/OnixLabs.Security.Cryptography/Hash.Concantenate.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Constants.cs b/OnixLabs.Security.Cryptography/Hash.Constants.cs index 8f85ebe..df27540 100644 --- a/OnixLabs.Security.Cryptography/Hash.Constants.cs +++ b/OnixLabs.Security.Cryptography/Hash.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Create.cs b/OnixLabs.Security.Cryptography/Hash.Create.cs index 6b0b2da..d7540ac 100644 --- a/OnixLabs.Security.Cryptography/Hash.Create.cs +++ b/OnixLabs.Security.Cryptography/Hash.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Equatable.cs b/OnixLabs.Security.Cryptography/Hash.Equatable.cs index 61c475e..8a610a7 100644 --- a/OnixLabs.Security.Cryptography/Hash.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Hash.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.Parse.cs b/OnixLabs.Security.Cryptography/Hash.Parse.cs index 8155dac..742f87c 100644 --- a/OnixLabs.Security.Cryptography/Hash.Parse.cs +++ b/OnixLabs.Security.Cryptography/Hash.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.To.cs b/OnixLabs.Security.Cryptography/Hash.To.cs index 4abef60..9f54df6 100644 --- a/OnixLabs.Security.Cryptography/Hash.To.cs +++ b/OnixLabs.Security.Cryptography/Hash.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hash.cs b/OnixLabs.Security.Cryptography/Hash.cs index e31eb1f..b346d04 100644 --- a/OnixLabs.Security.Cryptography/Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs index ad53ecf..7e79dfb 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs index 7c96a8b..04419ae 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs index 21be3ae..d370b5c 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.cs index 567d918..39df328 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs index 4b1d21e..962a98a 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs index 5ef8bfd..1c15d62 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs index b839db3..3424be3 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs index 494c1b4..ab6780d 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs index b10ee8f..5e29f08 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.cs index 71de157..3ab0ea7 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Compute.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs index f32c44a..f5f9ffb 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs index 0a57030..f2f3333 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs index 219cd1c..29c24ab 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs index 22c4855..af81aae 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs index e6345e8..0a022fe 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs index a0bc69a..5fd31ec 100644 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs +++ b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Constants.cs b/OnixLabs.Security.Cryptography/Hmac.Constants.cs index 0436605..e75bf8a 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Constants.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Create.cs b/OnixLabs.Security.Cryptography/Hmac.Create.cs index c22f53f..ed1f1de 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Create.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs index b75e99b..3361ae5 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Parse.cs b/OnixLabs.Security.Cryptography/Hmac.Parse.cs index e28cb38..281615f 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Parse.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Parse.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.To.cs b/OnixLabs.Security.Cryptography/Hmac.To.cs index 77d053d..aa47272 100644 --- a/OnixLabs.Security.Cryptography/Hmac.To.cs +++ b/OnixLabs.Security.Cryptography/Hmac.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.Verify.cs b/OnixLabs.Security.Cryptography/Hmac.Verify.cs index 8e7e78d..3cb2407 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Verify.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.cs index 08b76f7..7de8b96 100644 --- a/OnixLabs.Security.Cryptography/Hmac.cs +++ b/OnixLabs.Security.Cryptography/Hmac.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/IHashable.cs b/OnixLabs.Security.Cryptography/IHashable.cs index fff2f8f..48f2340 100644 --- a/OnixLabs.Security.Cryptography/IHashable.cs +++ b/OnixLabs.Security.Cryptography/IHashable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/KeyPair.Create.cs b/OnixLabs.Security.Cryptography/KeyPair.Create.cs index ecaa985..fe217b8 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.Create.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs index ed5d5f0..f596d4c 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/KeyPair.From.cs b/OnixLabs.Security.Cryptography/KeyPair.From.cs index f1e4387..c9e030e 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.From.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.From.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/KeyPair.cs b/OnixLabs.Security.Cryptography/KeyPair.cs index 501601e..19af1c4 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Build.cs b/OnixLabs.Security.Cryptography/MerkleTree.Build.cs index 26f30d4..c7f4e68 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Build.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Build.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs b/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs index 87e4e2e..ba4f110 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs index 8f690b4..13dcff7 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs index 2a0c3f5..6bde4b8 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs index acae77b..e1cee7e 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs index 2021787..5b42d3b 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Get.cs b/OnixLabs.Security.Cryptography/MerkleTree.Get.cs index be1e9bc..bb8efb3 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Get.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.To.cs b/OnixLabs.Security.Cryptography/MerkleTree.To.cs index 9cd1dfb..88468c9 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.To.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/MerkleTree.cs b/OnixLabs.Security.Cryptography/MerkleTree.cs index 1c07d0a..0fa9540 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs b/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs index e1ba46a..6960d93 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Export.cs b/OnixLabs.Security.Cryptography/PrivateKey.Export.cs index 44dc662..0721de3 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Export.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Get.cs b/OnixLabs.Security.Cryptography/PrivateKey.Get.cs index b9c6233..9fb0252 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs index fc0d80a..3982149 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.To.cs b/OnixLabs.Security.Cryptography/PrivateKey.To.cs index 4366e39..51cdb96 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.To.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PrivateKey.cs b/OnixLabs.Security.Cryptography/PrivateKey.cs index 8622dc0..1cc3573 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs b/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs index fc0a605..1aa3180 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PublicKey.To.cs b/OnixLabs.Security.Cryptography/PublicKey.To.cs index 48b5210..c3bacf7 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.To.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PublicKey.Verify.cs b/OnixLabs.Security.Cryptography/PublicKey.Verify.cs index 11489c1..8831454 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/PublicKey.cs b/OnixLabs.Security.Cryptography/PublicKey.cs index 39872db..9a6ed24 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs index c84e1de..2a27fe3 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs index a2df692..38448ff 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs index 69f119d..a47cdcc 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs index 2d4f82c..546f72b 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs index aabf49e..2fb8511 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs index 4496ca3..b54c0c7 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.cs index 6de4643..8e12f38 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs index 898d221..93acd1e 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs index 772b9d3..3b290b2 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs index 08205e9..c131f33 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.cs index 8b8252e..8b4798c 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Salt.Create.cs b/OnixLabs.Security.Cryptography/Salt.Create.cs index ddbb4fc..a5ee779 100644 --- a/OnixLabs.Security.Cryptography/Salt.Create.cs +++ b/OnixLabs.Security.Cryptography/Salt.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Salt.Equatable.cs b/OnixLabs.Security.Cryptography/Salt.Equatable.cs index 4d10020..e59e207 100644 --- a/OnixLabs.Security.Cryptography/Salt.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Salt.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Salt.To.cs b/OnixLabs.Security.Cryptography/Salt.To.cs index fad7cdb..ac95852 100644 --- a/OnixLabs.Security.Cryptography/Salt.To.cs +++ b/OnixLabs.Security.Cryptography/Salt.To.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Salt.cs b/OnixLabs.Security.Cryptography/Salt.cs index cfac012..4a8ac72 100644 --- a/OnixLabs.Security.Cryptography/Salt.cs +++ b/OnixLabs.Security.Cryptography/Salt.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3.Create.cs b/OnixLabs.Security.Cryptography/Sha3.Create.cs index 84ab6fa..0fc5ce1 100644 --- a/OnixLabs.Security.Cryptography/Sha3.Create.cs +++ b/OnixLabs.Security.Cryptography/Sha3.Create.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3.Permute.cs b/OnixLabs.Security.Cryptography/Sha3.Permute.cs index 001b979..3af16ff 100644 --- a/OnixLabs.Security.Cryptography/Sha3.Permute.cs +++ b/OnixLabs.Security.Cryptography/Sha3.Permute.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3.cs b/OnixLabs.Security.Cryptography/Sha3.cs index 2319244..84f0cb3 100644 --- a/OnixLabs.Security.Cryptography/Sha3.cs +++ b/OnixLabs.Security.Cryptography/Sha3.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Sha3Hash224.cs index d50e78e..a589334 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash224.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash224.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Sha3Hash256.cs index d589da2..0bd953a 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash256.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Sha3Hash384.cs index 037166e..fab67ec 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash384.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash384.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Sha3Hash512.cs index 1249222..bfbe7b8 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash512.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash512.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Sha3Shake128.cs index 470591b..45b6380 100644 --- a/OnixLabs.Security.Cryptography/Sha3Shake128.cs +++ b/OnixLabs.Security.Cryptography/Sha3Shake128.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Security.Cryptography/Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Sha3Shake256.cs index b13343b..d418a08 100644 --- a/OnixLabs.Security.Cryptography/Sha3Shake256.cs +++ b/OnixLabs.Security.Cryptography/Sha3Shake256.cs @@ -1,4 +1,4 @@ -// Copyright 2020-2023 ONIXLabs +// Copyright © 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/onixlabs-dotnet.sln.DotSettings b/onixlabs-dotnet.sln.DotSettings index ba6a0f8..4b838e7 100644 --- a/onixlabs-dotnet.sln.DotSettings +++ b/onixlabs-dotnet.sln.DotSettings @@ -37,6 +37,7 @@ limitations under the License. True True True + True True True True From b4e356409f7511c6990a6b49b572201325b2594f Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Sun, 22 Oct 2023 23:18:50 +0100 Subject: [PATCH 04/14] feature/api update (#29) Updated collection creation and return types changed to IReadOnlyList --- .editorconfig | 2 +- OnixLabs.Core.UnitTests/PreconditionTests.cs | 24 ++++++++++--- OnixLabs.Core/Collections/Collection.Empty.cs | 16 ++++----- OnixLabs.Core/Collections/Collection.Of.cs | 36 +++++++++---------- OnixLabs.Core/Enumeration.Get.cs | 10 +++--- OnixLabs.Core/Preconditions.cs | 9 ++--- OnixLabs.Playground/Program.cs | 2 +- .../MerkleTree.Generic.Get.cs | 2 +- .../MerkleTree.Get.cs | 2 +- 9 files changed, 61 insertions(+), 42 deletions(-) diff --git a/.editorconfig b/.editorconfig index a091931..9e4210f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,4 +2,4 @@ root = true [*] max_line_length = 140 -insert_final_newline = true +insert_final_newline = true \ No newline at end of file diff --git a/OnixLabs.Core.UnitTests/PreconditionTests.cs b/OnixLabs.Core.UnitTests/PreconditionTests.cs index b724d33..e497f3d 100644 --- a/OnixLabs.Core.UnitTests/PreconditionTests.cs +++ b/OnixLabs.Core.UnitTests/PreconditionTests.cs @@ -23,24 +23,40 @@ public sealed class PreconditionTests [Fact(DisplayName = "Check should throw an ArgumentException when the condition is false")] public void CheckShouldProduceExpectedResult() { - Assert.Throws(() => Check(false)); + // When + InvalidOperationException exception = Assert.Throws(() => Check(false)); + + // Then + Assert.Equal("Check requirement failed.", exception.Message); } [Fact(DisplayName = "CheckNotNull should throw an ArgumentNullException when the condition is null")] public void CheckNotNullShouldProduceExpectedResult() { - Assert.Throws(() => CheckNotNull(null)); + // When + InvalidOperationException exception = Assert.Throws(() => CheckNotNull(null)); + + // Then + Assert.Equal("Argument must not be null.", exception.Message); } [Fact(DisplayName = "Require should throw an ArgumentException when the condition is false")] public void RequireShouldProduceExpectedResult() { - Assert.Throws(() => Require(false)); + // When + ArgumentException exception = Assert.Throws(() => Require(false)); + + // Then + Assert.Equal("Argument requirement failed.", exception.Message); } [Fact(DisplayName = "RequireNotNull should throw an ArgumentNullException when the condition is null")] public void RequireNotNullShouldProduceExpectedResult() { - Assert.Throws(() => RequireNotNull(null)); + // When + ArgumentNullException exception = Assert.Throws(() => RequireNotNull(null)); + + // Then + Assert.Equal("Argument must not be null.", exception.Message); } } diff --git a/OnixLabs.Core/Collections/Collection.Empty.cs b/OnixLabs.Core/Collections/Collection.Empty.cs index b77d2cc..ecccf14 100644 --- a/OnixLabs.Core/Collections/Collection.Empty.cs +++ b/OnixLabs.Core/Collections/Collection.Empty.cs @@ -51,7 +51,7 @@ public static T[] EmptyArray() /// Returns an empty immutable array. public static ImmutableArray EmptyImmutableArray() { - return EmptyArray().ToImmutableArray(); + return ImmutableArray.Empty; } /// @@ -71,7 +71,7 @@ public static List EmptyList() /// Returns an empty immutable list. public static ImmutableList EmptyImmutableList() { - return EmptyList().ToImmutableList(); + return ImmutableList.Empty; } /// @@ -93,7 +93,7 @@ public static Dictionary EmptyDictionary() where TKe /// Returns an empty immutable dictionary. public static ImmutableDictionary EmptyImmutableDictionary() where TKey : notnull { - return EmptyDictionary().ToImmutableDictionary(); + return ImmutableDictionary.Empty; } /// @@ -115,7 +115,7 @@ public static SortedDictionary EmptySortedDictionary /// Returns an empty immutable sorted dictionary. public static ImmutableSortedDictionary EmptyImmutableSortedDictionary() where TKey : notnull { - return EmptySortedDictionary().ToImmutableSortedDictionary(); + return ImmutableSortedDictionary.Empty; } /// @@ -135,7 +135,7 @@ public static HashSet EmptyHashSet() /// Returns an empty immutable hash set. public static ImmutableHashSet EmptyImmutableHashSet() { - return EmptyHashSet().ToImmutableHashSet(); + return ImmutableHashSet.Empty; } /// @@ -155,7 +155,7 @@ public static SortedSet EmptySortedSet() /// Returns an empty immutable sorted set. public static ImmutableSortedSet EmptyImmutableSortedSet() { - return EmptySortedSet().ToImmutableSortedSet(); + return ImmutableSortedSet.Empty; } /// @@ -175,7 +175,7 @@ public static Stack EmptyStack() /// Returns an empty immutable stack. public static ImmutableStack EmptyImmutableStack() { - return ImmutableStack.Create(); + return ImmutableStack.Empty; } /// @@ -195,6 +195,6 @@ public static Queue EmptyQueue() /// Returns an empty immutable queue. public static ImmutableQueue EmptyImmutableQueue() { - return ImmutableQueue.Create(); + return ImmutableQueue.Empty; } } diff --git a/OnixLabs.Core/Collections/Collection.Of.cs b/OnixLabs.Core/Collections/Collection.Of.cs index 3e7a095..657aad2 100644 --- a/OnixLabs.Core/Collections/Collection.Of.cs +++ b/OnixLabs.Core/Collections/Collection.Of.cs @@ -28,7 +28,7 @@ public static partial class Collection /// Returns an enumerable populated with the specified items. public static IEnumerable EnumerableOf(params T[] items) { - return items.Copy(); + return items; } /// @@ -39,7 +39,7 @@ public static IEnumerable EnumerableOf(params T[] items) /// Returns an array populated with the specified items. public static T[] ArrayOf(params T[] items) { - return items.Copy(); + return items; } /// @@ -50,7 +50,7 @@ public static T[] ArrayOf(params T[] items) /// Returns an immutable array populated with the specified items. public static ImmutableArray ImmutableArrayOf(params T[] items) { - return ArrayOf(items).ToImmutableArray(); + return ImmutableArray.Create(items); } /// @@ -61,7 +61,7 @@ public static ImmutableArray ImmutableArrayOf(params T[] items) /// Returns a list populated with the specified items. public static List ListOf(params T[] items) { - return new List(items.Copy()); + return new List(items); } /// @@ -72,7 +72,7 @@ public static List ListOf(params T[] items) /// Returns an immutable list populated with the specified items. public static ImmutableList ImmutableListOf(params T[] items) { - return ListOf(items).ToImmutableList(); + return ImmutableList.Create(items); } /// @@ -84,7 +84,7 @@ public static ImmutableList ImmutableListOf(params T[] items) /// Returns a dictionary populated with the specified items. public static Dictionary DictionaryOf(params KeyValuePair[] items) where TKey : notnull { - return new Dictionary(items.Copy()); + return new Dictionary(items); } /// @@ -109,7 +109,7 @@ public static Dictionary DictionaryOf(params (TKey k public static ImmutableDictionary ImmutableDictionaryOf( params KeyValuePair[] items) where TKey : notnull { - return DictionaryOf(items).ToImmutableDictionary(); + return ImmutableDictionary.CreateRange(items); } /// @@ -122,7 +122,7 @@ public static ImmutableDictionary ImmutableDictionaryOf ImmutableDictionaryOf( params (TKey key, TValue value)[] items) where TKey : notnull { - return DictionaryOf(items).ToImmutableDictionary(); + return ImmutableDictionary.CreateRange(items.Select(item => new KeyValuePair(item.key, item.value))); } /// @@ -161,7 +161,7 @@ public static SortedDictionary SortedDictionaryOf( public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( params KeyValuePair[] items) where TKey : notnull { - return SortedDictionaryOf(items).ToImmutableSortedDictionary(); + return ImmutableSortedDictionary.CreateRange(items); } /// @@ -174,7 +174,7 @@ public static ImmutableSortedDictionary ImmutableSortedDictionaryO public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( params (TKey key, TValue value)[] items) where TKey : notnull { - return SortedDictionaryOf(items).ToImmutableSortedDictionary(); + return ImmutableSortedDictionary.CreateRange(items.Select(item => new KeyValuePair(item.key, item.value))); } /// @@ -185,7 +185,7 @@ public static ImmutableSortedDictionary ImmutableSortedDictionaryO /// Returns a hash set populated with the specified items. public static HashSet HashSetOf(params T[] items) { - return new HashSet(items.Copy()); + return new HashSet(items); } /// @@ -196,7 +196,7 @@ public static HashSet HashSetOf(params T[] items) /// Returns an immutable hash set populated with the specified items. public static ImmutableHashSet ImmutableHashSetOf(params T[] items) { - return HashSetOf(items).ToImmutableHashSet(); + return ImmutableHashSet.Create(items); } /// @@ -207,7 +207,7 @@ public static ImmutableHashSet ImmutableHashSetOf(params T[] items) /// Returns a sorted set populated with the specified items. public static SortedSet SortedSetOf(params T[] items) { - return new SortedSet(items.Copy()); + return new SortedSet(items); } /// @@ -218,7 +218,7 @@ public static SortedSet SortedSetOf(params T[] items) /// Returns an immutable sorted set populated with the specified items. public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) { - return SortedSetOf(items).ToImmutableSortedSet(); + return ImmutableSortedSet.Create(items); } /// @@ -229,7 +229,7 @@ public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) /// Returns a stack populated with the specified items. public static Stack StackOf(params T[] items) { - return new Stack(items.Copy()); + return new Stack(items); } /// @@ -240,7 +240,7 @@ public static Stack StackOf(params T[] items) /// Returns an immutable stack populated with the specified items. public static ImmutableStack ImmutableStackOf(params T[] items) { - return ImmutableStack.Create(items.Copy()); + return ImmutableStack.Create(items); } /// @@ -251,7 +251,7 @@ public static ImmutableStack ImmutableStackOf(params T[] items) /// Returns a queue populated with the specified items. public static Queue QueueOf(params T[] items) { - return new Queue(items.Copy()); + return new Queue(items); } /// @@ -262,6 +262,6 @@ public static Queue QueueOf(params T[] items) /// Returns an immutable queue populated with the specified items. public static ImmutableQueue ImmutableQueueOf(params T[] items) { - return ImmutableQueue.Create(items.Copy()); + return ImmutableQueue.Create(items); } } diff --git a/OnixLabs.Core/Enumeration.Get.cs b/OnixLabs.Core/Enumeration.Get.cs index 68ae378..a7e3af8 100644 --- a/OnixLabs.Core/Enumeration.Get.cs +++ b/OnixLabs.Core/Enumeration.Get.cs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Reflection; @@ -19,13 +20,14 @@ namespace OnixLabs.Core; +// ReSharper disable ReturnTypeCanBeEnumerable.Global public abstract partial class Enumeration { /// /// Gets all of the enumeration entries for the current type. /// /// Returns all of the enumeration entries for the current type. - public static ImmutableHashSet GetAll() + public static IReadOnlySet GetAll() { return typeof(T) .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) @@ -38,7 +40,7 @@ public static ImmutableHashSet GetAll() /// Gets all of the enumeration entries for the current type. /// /// Returns all of the enumeration entries for the current type. - public static ImmutableHashSet<(int Value, string Name)> GetEntries() + public static IReadOnlySet<(int Value, string Name)> GetEntries() { return GetAll().Select(entry => entry.ToEntry()).ToImmutableHashSet(); } @@ -47,7 +49,7 @@ public static ImmutableHashSet GetAll() /// Gets all of the enumeration names for the current type. /// /// Returns all of the enumeration names for the current type. - public static ImmutableHashSet GetNames() + public static IReadOnlySet GetNames() { return GetAll().Select(entry => entry.Name).ToImmutableHashSet(); } @@ -56,7 +58,7 @@ public static ImmutableHashSet GetNames() /// Gets all of the enumeration values for the current type. /// /// Returns all of the enumeration values for the current type. - public static ImmutableHashSet GetValues() + public static IReadOnlySet GetValues() { return GetAll().Select(entry => entry.Value).ToImmutableHashSet(); } diff --git a/OnixLabs.Core/Preconditions.cs b/OnixLabs.Core/Preconditions.cs index f217b43..b255ee0 100644 --- a/OnixLabs.Core/Preconditions.cs +++ b/OnixLabs.Core/Preconditions.cs @@ -29,7 +29,7 @@ public static class Preconditions /// The exception message to throw in the event that the condition fails. /// If the condition fails. [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static void Check(bool condition, string message = "Check failed.") + public static void Check(bool condition, string message = "Check requirement failed.") { if (!condition) throw new InvalidOperationException(message); } @@ -43,7 +43,7 @@ public static void Check(bool condition, string message = "Check failed.") /// Returns the specified value as non-nullable in the event that the value is not null. /// If the condition fails because the value is null. [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static T CheckNotNull(T? value, string message = "Null check failed.") where T : notnull + public static T CheckNotNull(T? value, string message = "Argument must not be null.") where T : notnull { return value ?? throw new InvalidOperationException(message); } @@ -71,8 +71,9 @@ public static void Require(bool condition, string message = "Argument requiremen /// Returns the specified value as non-nullable in the event that the value is not null. /// If the condition fails because the value is null. [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] - public static T RequireNotNull(T? value, string message = "Argument must be null.", string? parameterName = null) where T : notnull + public static T RequireNotNull(T? value, string message = "Argument must not be null.", string? parameterName = null) + where T : notnull { - return value ?? throw new ArgumentNullException(message, parameterName); + return value ?? throw new ArgumentNullException(parameterName, message); } } diff --git a/OnixLabs.Playground/Program.cs b/OnixLabs.Playground/Program.cs index d7c13e1..6674ac3 100644 --- a/OnixLabs.Playground/Program.cs +++ b/OnixLabs.Playground/Program.cs @@ -16,7 +16,7 @@ namespace OnixLabs.Playground; internal static class Program { - private static void Main(string[] args) + public static void Main() { } } diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs index e1cee7e..8bff690 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs @@ -33,7 +33,7 @@ public MerkleTree ToMerkleTree() /// Obtains the leaf values from the current . /// /// Returns an containing the leaf values from the current . - public ImmutableList GetLeafValues() + public IReadOnlyList GetLeafValues() { ICollection result = EmptyList(); CollectLeafValues(this, result); diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Get.cs b/OnixLabs.Security.Cryptography/MerkleTree.Get.cs index bb8efb3..fd1b661 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Get.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Get.cs @@ -23,7 +23,7 @@ public abstract partial class MerkleTree /// Obtains the leaf hashes from the current . /// /// Returns an containing the leaf hashes from the current . - public ImmutableList GetLeafHashes() + public IReadOnlyList GetLeafHashes() { ICollection result = EmptyList(); CollectLeafHashes(this, result); From 9a0a844d8bf21ebffb4d3e332194fdf536dad8e3 Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Sat, 11 Nov 2023 21:41:24 +0000 Subject: [PATCH 05/14] Added Temperature implementation (#30) --- .../Units/TemperatureTests.cs | 470 ++++++++++++++++++ OnixLabs.Core/OnixLabs.Core.csproj | 1 + OnixLabs.Core/Units/Temperature.Arithmetic.cs | 106 ++++ OnixLabs.Core/Units/Temperature.Comparable.cs | 100 ++++ OnixLabs.Core/Units/Temperature.Constants.cs | 28 ++ OnixLabs.Core/Units/Temperature.Equatable.cs | 82 +++ OnixLabs.Core/Units/Temperature.From.cs | 88 ++++ .../Units/Temperature.Static.Arithmetic.cs | 71 +++ .../Units/Temperature.Static.Comparison.cs | 45 ++ .../Units/Temperature.Static.From.cs | 97 ++++ OnixLabs.Core/Units/Temperature.To.cs | 65 +++ OnixLabs.Core/Units/Temperature.cs | 68 +++ 12 files changed, 1221 insertions(+) create mode 100644 OnixLabs.Core.UnitTests/Units/TemperatureTests.cs create mode 100644 OnixLabs.Core/Units/Temperature.Arithmetic.cs create mode 100644 OnixLabs.Core/Units/Temperature.Comparable.cs create mode 100644 OnixLabs.Core/Units/Temperature.Constants.cs create mode 100644 OnixLabs.Core/Units/Temperature.Equatable.cs create mode 100644 OnixLabs.Core/Units/Temperature.From.cs create mode 100644 OnixLabs.Core/Units/Temperature.Static.Arithmetic.cs create mode 100644 OnixLabs.Core/Units/Temperature.Static.Comparison.cs create mode 100644 OnixLabs.Core/Units/Temperature.Static.From.cs create mode 100644 OnixLabs.Core/Units/Temperature.To.cs create mode 100644 OnixLabs.Core/Units/Temperature.cs diff --git a/OnixLabs.Core.UnitTests/Units/TemperatureTests.cs b/OnixLabs.Core.UnitTests/Units/TemperatureTests.cs new file mode 100644 index 0000000..1548cd8 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Units/TemperatureTests.cs @@ -0,0 +1,470 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using OnixLabs.Core.Units; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Units; + +public sealed class TemperatureTests +{ + [Theory(DisplayName = "Temperature.FromKelvin should produce the expected conversion results")] + [InlineData(-1000, -1273.15, 2059.73, -2259.67, -420.14, -1018.52, -1800)] + [InlineData(-100, -373.15, 709.72, -639.67, -123.14, -298.52, -180)] + [InlineData(-90, -363.15, 694.72, -621.67, -119.84, -290.52, -162)] + [InlineData(-80, -353.15, 679.72, -603.67, -116.54, -282.52, -144)] + [InlineData(-70, -343.15, 664.72, -585.67, -113.24, -274.52, -126)] + [InlineData(-60, -333.15, 649.72, -567.67, -109.94, -266.52, -108)] + [InlineData(-50, -323.15, 634.72, -549.67, -106.64, -258.52, -90)] + [InlineData(-40, -313.15, 619.72, -531.67, -103.34, -250.52, -72)] + [InlineData(-30, -303.15, 604.72, -513.67, -100.04, -242.52, -54)] + [InlineData(-20, -293.15, 589.72, -495.67, -96.74, -234.52, -36)] + [InlineData(-10, -283.15, 574.72, -477.67, -93.44, -226.52, -18)] + [InlineData(-9, -282.15, 573.22, -475.87, -93.11, -225.72, -16.2)] + [InlineData(-8, -281.15, 571.72, -474.07, -92.78, -224.92, -14.4)] + [InlineData(-7, -280.15, 570.22, -472.27, -92.45, -224.12, -12.6)] + [InlineData(-6, -279.15, 568.72, -470.47, -92.12, -223.32, -10.8)] + [InlineData(-5, -278.15, 567.22, -468.67, -91.79, -222.52, -9)] + [InlineData(-4, -277.15, 565.72, -466.87, -91.46, -221.72, -7.2)] + [InlineData(-3, -276.15, 564.22, -465.07, -91.13, -220.92, -5.4)] + [InlineData(-2, -275.15, 562.72, -463.27, -90.8, -220.12, -3.6)] + [InlineData(-1, -274.15, 561.22, -461.47, -90.47, -219.32, -1.8)] + [InlineData(0, -273.15, 559.72, -459.67, -90.14, -218.52, 0)] + [InlineData(1, -272.15, 558.22, -457.87, -89.81, -217.72, 1.8)] + [InlineData(2, -271.15, 556.72, -456.07, -89.48, -216.92, 3.6)] + [InlineData(3, -270.15, 555.22, -454.27, -89.15, -216.12, 5.4)] + [InlineData(4, -269.15, 553.72, -452.47, -88.82, -215.32, 7.2)] + [InlineData(5, -268.15, 552.22, -450.67, -88.49, -214.52, 9)] + [InlineData(6, -267.15, 550.72, -448.87, -88.16, -213.72, 10.8)] + [InlineData(7, -266.15, 549.22, -447.07, -87.83, -212.92, 12.6)] + [InlineData(8, -265.15, 547.72, -445.27, -87.5, -212.12, 14.4)] + [InlineData(9, -264.15, 546.22, -443.47, -87.17, -211.32, 16.2)] + [InlineData(10, -263.15, 544.72, -441.67, -86.84, -210.52, 18)] + [InlineData(20, -253.15, 529.72, -423.67, -83.54, -202.52, 36)] + [InlineData(30, -243.15, 514.72, -405.67, -80.24, -194.52, 54)] + [InlineData(40, -233.15, 499.72, -387.67, -76.94, -186.52, 72)] + [InlineData(50, -223.15, 484.72, -369.67, -73.64, -178.52, 90)] + [InlineData(60, -213.15, 469.72, -351.67, -70.34, -170.52, 108)] + [InlineData(70, -203.15, 454.72, -333.67, -67.04, -162.52, 126)] + [InlineData(80, -193.15, 439.72, -315.67, -63.74, -154.52, 144)] + [InlineData(90, -183.15, 424.72, -297.67, -60.44, -146.52, 162)] + [InlineData(100, -173.15, 409.72, -279.67, -57.14, -138.52, 180)] + [InlineData(1000, 726.85, -940.28, 1340.33, 239.86, 581.48, 1800)] + public void TemperatureFromKelvinShouldProduceTheExpectedConversionResults( + double kelvin, + double celsius, + double delisle, + double fahrenheit, + double newton, + double reaumur, + double rankine) + { + // Arrange / Act + Temperature temperature = Temperature.FromKelvin(kelvin); + + // Assert + Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); + Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); + Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); + Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); + Assert.Equal(newton, Math.Round(temperature.Newton, 2)); + Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); + Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); + } + + [Theory(DisplayName = "Temperature.FromCelsius should produce the expected conversion results")] + [InlineData(-1000, -726.85, 1650, -1768, -330, -800, -1308.33)] + [InlineData(-100, 173.15, 300, -148, -33, -80, 311.67)] + [InlineData(-90, 183.15, 285, -130, -29.7, -72, 329.67)] + [InlineData(-80, 193.15, 270, -112, -26.4, -64, 347.67)] + [InlineData(-70, 203.15, 255, -94, -23.1, -56, 365.67)] + [InlineData(-60, 213.15, 240, -76, -19.8, -48, 383.67)] + [InlineData(-50, 223.15, 225, -58, -16.5, -40, 401.67)] + [InlineData(-40, 233.15, 210, -40, -13.2, -32, 419.67)] + [InlineData(-30, 243.15, 195, -22, -9.9, -24, 437.67)] + [InlineData(-20, 253.15, 180, -4, -6.6, -16, 455.67)] + [InlineData(-10, 263.15, 165, 14, -3.3, -8, 473.67)] + [InlineData(-9, 264.15, 163.5, 15.8, -2.97, -7.2, 475.47)] + [InlineData(-8, 265.15, 162, 17.6, -2.64, -6.4, 477.27)] + [InlineData(-7, 266.15, 160.5, 19.4, -2.31, -5.6, 479.07)] + [InlineData(-6, 267.15, 159, 21.2, -1.98, -4.8, 480.87)] + [InlineData(-5, 268.15, 157.5, 23, -1.65, -4, 482.67)] + [InlineData(-4, 269.15, 156, 24.8, -1.32, -3.2, 484.47)] + [InlineData(-3, 270.15, 154.5, 26.6, -0.99, -2.4, 486.27)] + [InlineData(-2, 271.15, 153, 28.4, -0.66, -1.6, 488.07)] + [InlineData(-1, 272.15, 151.5, 30.2, -0.33, -0.8, 489.87)] + [InlineData(0, 273.15, 150, 32, 0, 0, 491.67)] + [InlineData(1, 274.15, 148.5, 33.8, 0.33, 0.8, 493.47)] + [InlineData(2, 275.15, 147, 35.6, 0.66, 1.6, 495.27)] + [InlineData(3, 276.15, 145.5, 37.4, 0.99, 2.4, 497.07)] + [InlineData(4, 277.15, 144, 39.2, 1.32, 3.2, 498.87)] + [InlineData(5, 278.15, 142.5, 41, 1.65, 4, 500.67)] + [InlineData(6, 279.15, 141, 42.8, 1.98, 4.8, 502.47)] + [InlineData(7, 280.15, 139.5, 44.6, 2.31, 5.6, 504.27)] + [InlineData(8, 281.15, 138, 46.4, 2.64, 6.4, 506.07)] + [InlineData(9, 282.15, 136.5, 48.2, 2.97, 7.2, 507.87)] + [InlineData(10, 283.15, 135, 50, 3.3, 8, 509.67)] + [InlineData(20, 293.15, 120, 68, 6.6, 16, 527.67)] + [InlineData(30, 303.15, 105, 86, 9.9, 24, 545.67)] + [InlineData(40, 313.15, 90, 104, 13.2, 32, 563.67)] + [InlineData(50, 323.15, 75, 122, 16.5, 40, 581.67)] + [InlineData(60, 333.15, 60, 140, 19.8, 48, 599.67)] + [InlineData(70, 343.15, 45, 158, 23.1, 56, 617.67)] + [InlineData(80, 353.15, 30, 176, 26.4, 64, 635.67)] + [InlineData(90, 363.15, 15, 194, 29.7, 72, 653.67)] + [InlineData(100, 373.15, 0, 212, 33, 80, 671.67)] + [InlineData(1000, 1273.15, -1350, 1832, 330, 800, 2291.67)] + public void TemperatureFromCelsiusShouldProduceTheExpectedConversionResults( + double celsius, + double kelvin, + double delisle, + double fahrenheit, + double newton, + double reaumur, + double rankine) + { + // Arrange / Act + Temperature temperature = Temperature.FromCelsius(celsius); + + // Assert + Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); + Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); + Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); + Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); + Assert.Equal(newton, Math.Round(temperature.Newton, 2)); + Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); + Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); + } + + [Theory(DisplayName = "Temperature.FromDelisle should produce the expected conversion results")] + [InlineData(-1000, 1039.82, 766.67, 1412, 253, 613.33, 1871.67)] + [InlineData(-100, 439.82, 166.67, 332, 55, 133.33, 791.67)] + [InlineData(-90, 433.15, 160, 320, 52.8, 128, 779.67)] + [InlineData(-80, 426.48, 153.33, 308, 50.6, 122.67, 767.67)] + [InlineData(-70, 419.82, 146.67, 296, 48.4, 117.33, 755.67)] + [InlineData(-60, 413.15, 140, 284, 46.2, 112, 743.67)] + [InlineData(-50, 406.48, 133.33, 272, 44, 106.67, 731.67)] + [InlineData(-40, 399.82, 126.67, 260, 41.8, 101.33, 719.67)] + [InlineData(-30, 393.15, 120, 248, 39.6, 96, 707.67)] + [InlineData(-20, 386.48, 113.33, 236, 37.4, 90.67, 695.67)] + [InlineData(-10, 379.82, 106.67, 224, 35.2, 85.33, 683.67)] + [InlineData(-9, 379.15, 106, 222.8, 34.98, 84.8, 682.47)] + [InlineData(-8, 378.48, 105.33, 221.6, 34.76, 84.27, 681.27)] + [InlineData(-7, 377.82, 104.67, 220.4, 34.54, 83.73, 680.07)] + [InlineData(-6, 377.15, 104, 219.2, 34.32, 83.2, 678.87)] + [InlineData(-5, 376.48, 103.33, 218, 34.1, 82.67, 677.67)] + [InlineData(-4, 375.82, 102.67, 216.8, 33.88, 82.13, 676.47)] + [InlineData(-3, 375.15, 102, 215.6, 33.66, 81.6, 675.27)] + [InlineData(-2, 374.48, 101.33, 214.4, 33.44, 81.07, 674.07)] + [InlineData(-1, 373.82, 100.67, 213.2, 33.22, 80.53, 672.87)] + [InlineData(0, 373.15, 100, 212, 33, 80, 671.67)] + [InlineData(1, 372.48, 99.33, 210.8, 32.78, 79.47, 670.47)] + [InlineData(2, 371.82, 98.67, 209.6, 32.56, 78.93, 669.27)] + [InlineData(3, 371.15, 98, 208.4, 32.34, 78.4, 668.07)] + [InlineData(4, 370.48, 97.33, 207.2, 32.12, 77.87, 666.87)] + [InlineData(5, 369.82, 96.67, 206, 31.9, 77.33, 665.67)] + [InlineData(6, 369.15, 96, 204.8, 31.68, 76.8, 664.47)] + [InlineData(7, 368.48, 95.33, 203.6, 31.46, 76.27, 663.27)] + [InlineData(8, 367.82, 94.67, 202.4, 31.24, 75.73, 662.07)] + [InlineData(9, 367.15, 94, 201.2, 31.02, 75.2, 660.87)] + [InlineData(10, 366.48, 93.33, 200, 30.8, 74.67, 659.67)] + [InlineData(20, 359.82, 86.67, 188, 28.6, 69.33, 647.67)] + [InlineData(30, 353.15, 80, 176, 26.4, 64, 635.67)] + [InlineData(40, 346.48, 73.33, 164, 24.2, 58.67, 623.67)] + [InlineData(50, 339.82, 66.67, 152, 22, 53.33, 611.67)] + [InlineData(60, 333.15, 60, 140, 19.8, 48, 599.67)] + [InlineData(70, 326.48, 53.33, 128, 17.6, 42.67, 587.67)] + [InlineData(80, 319.82, 46.67, 116, 15.4, 37.33, 575.67)] + [InlineData(90, 313.15, 40, 104, 13.2, 32, 563.67)] + [InlineData(100, 306.48, 33.33, 92, 11, 26.67, 551.67)] + [InlineData(1000, -293.52, -566.67, -988, -187, -453.33, -528.33)] + public void TemperatureFromDelisleShouldProduceTheExpectedConversionResults( + double delisle, + double kelvin, + double celsius, + double fahrenheit, + double newton, + double reaumur, + double rankine) + { + // Arrange / Act + Temperature temperature = Temperature.FromDelisle(delisle); + + // Assert + Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); + Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); + Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); + Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); + Assert.Equal(newton, Math.Round(temperature.Newton, 2)); + Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); + Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); + } + + [Theory(DisplayName = "Temperature.FromFahrenheit should produce the expected conversion results")] + [InlineData(-1000, -300.18, -573.33, 1010, -189.2, -458.67, -540.33)] + [InlineData(-100, 199.82, -73.33, 260, -24.2, -58.67, 359.67)] + [InlineData(-90, 205.37, -67.78, 251.67, -22.37, -54.22, 369.67)] + [InlineData(-80, 210.93, -62.22, 243.33, -20.53, -49.78, 379.67)] + [InlineData(-70, 216.48, -56.67, 235, -18.7, -45.33, 389.67)] + [InlineData(-60, 222.04, -51.11, 226.67, -16.87, -40.89, 399.67)] + [InlineData(-50, 227.59, -45.56, 218.33, -15.03, -36.44, 409.67)] + [InlineData(-40, 233.15, -40, 210, -13.2, -32, 419.67)] + [InlineData(-30, 238.71, -34.44, 201.67, -11.37, -27.56, 429.67)] + [InlineData(-20, 244.26, -28.89, 193.33, -9.53, -23.11, 439.67)] + [InlineData(-10, 249.82, -23.33, 185, -7.7, -18.67, 449.67)] + [InlineData(-9, 250.37, -22.78, 184.17, -7.52, -18.22, 450.67)] + [InlineData(-8, 250.93, -22.22, 183.33, -7.33, -17.78, 451.67)] + [InlineData(-7, 251.48, -21.67, 182.5, -7.15, -17.33, 452.67)] + [InlineData(-6, 252.04, -21.11, 181.67, -6.97, -16.89, 453.67)] + [InlineData(-5, 252.59, -20.56, 180.83, -6.78, -16.44, 454.67)] + [InlineData(-4, 253.15, -20, 180, -6.6, -16, 455.67)] + [InlineData(-3, 253.71, -19.44, 179.17, -6.42, -15.56, 456.67)] + [InlineData(-2, 254.26, -18.89, 178.33, -6.23, -15.11, 457.67)] + [InlineData(-1, 254.82, -18.33, 177.5, -6.05, -14.67, 458.67)] + [InlineData(-0, 255.37, -17.78, 176.67, -5.87, -14.22, 459.67)] + [InlineData(1, 255.93, -17.22, 175.83, -5.68, -13.78, 460.67)] + [InlineData(2, 256.48, -16.67, 175, -5.5, -13.33, 461.67)] + [InlineData(3, 257.04, -16.11, 174.17, -5.32, -12.89, 462.67)] + [InlineData(4, 257.59, -15.56, 173.33, -5.13, -12.44, 463.67)] + [InlineData(5, 258.15, -15, 172.5, -4.95, -12, 464.67)] + [InlineData(6, 258.71, -14.44, 171.67, -4.77, -11.56, 465.67)] + [InlineData(7, 259.26, -13.89, 170.83, -4.58, -11.11, 466.67)] + [InlineData(8, 259.82, -13.33, 170, -4.4, -10.67, 467.67)] + [InlineData(9, 260.37, -12.78, 169.17, -4.22, -10.22, 468.67)] + [InlineData(10, 260.93, -12.22, 168.33, -4.03, -9.78, 469.67)] + [InlineData(20, 266.48, -6.67, 160, -2.2, -5.33, 479.67)] + [InlineData(30, 272.04, -1.11, 151.67, -0.37, -0.89, 489.67)] + [InlineData(40, 277.59, 4.44, 143.33, 1.47, 3.56, 499.67)] + [InlineData(50, 283.15, 10, 135, 3.3, 8, 509.67)] + [InlineData(60, 288.71, 15.56, 126.67, 5.13, 12.44, 519.67)] + [InlineData(70, 294.26, 21.11, 118.33, 6.97, 16.89, 529.67)] + [InlineData(80, 299.82, 26.67, 110, 8.8, 21.33, 539.67)] + [InlineData(90, 305.37, 32.22, 101.67, 10.63, 25.78, 549.67)] + [InlineData(100, 310.93, 37.78, 93.33, 12.47, 30.22, 559.67)] + [InlineData(1000, 810.93, 537.78, -656.67, 177.47, 430.22, 1459.67)] + public void TemperatureFromFahrenheitShouldProduceTheExpectedConversionResults( + double fahrenheit, + double kelvin, + double celsius, + double delisle, + double newton, + double reaumur, + double rankine) + { + // Arrange / Act + Temperature temperature = Temperature.FromFahrenheit(fahrenheit); + + // Assert + Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); + Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); + Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); + Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); + Assert.Equal(newton, Math.Round(temperature.Newton, 2)); + Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); + Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); + } + + [Theory(DisplayName = "Temperature.FromNewton should produce the expected conversion results")] + [InlineData(-1000, -2757.15, -3030.3, 4695.45, -5422.55, -2424.24, -4962.88)] + [InlineData(-100, -29.88, -303.03, 604.55, -513.45, -242.42, -53.78)] + [InlineData(-90, 0.42, -272.73, 559.09, -458.91, -218.18, 0.76)] + [InlineData(-80, 30.73, -242.42, 513.64, -404.36, -193.94, 55.31)] + [InlineData(-70, 61.03, -212.12, 468.18, -349.82, -169.7, 109.85)] + [InlineData(-60, 91.33, -181.82, 422.73, -295.27, -145.45, 164.4)] + [InlineData(-50, 121.63, -151.52, 377.27, -240.73, -121.21, 218.94)] + [InlineData(-40, 151.94, -121.21, 331.82, -186.18, -96.97, 273.49)] + [InlineData(-30, 182.24, -90.91, 286.36, -131.64, -72.73, 328.03)] + [InlineData(-20, 212.54, -60.61, 240.91, -77.09, -48.48, 382.58)] + [InlineData(-10, 242.85, -30.3, 195.45, -22.55, -24.24, 437.12)] + [InlineData(-9, 245.88, -27.27, 190.91, -17.09, -21.82, 442.58)] + [InlineData(-8, 248.91, -24.24, 186.36, -11.64, -19.39, 448.03)] + [InlineData(-7, 251.94, -21.21, 181.82, -6.18, -16.97, 453.49)] + [InlineData(-6, 254.97, -18.18, 177.27, -0.73, -14.55, 458.94)] + [InlineData(-5, 258, -15.15, 172.73, 4.73, -12.12, 464.4)] + [InlineData(-4, 261.03, -12.12, 168.18, 10.18, -9.7, 469.85)] + [InlineData(-3, 264.06, -9.09, 163.64, 15.64, -7.27, 475.31)] + [InlineData(-2, 267.09, -6.06, 159.09, 21.09, -4.85, 480.76)] + [InlineData(-1, 270.12, -3.03, 154.55, 26.55, -2.42, 486.22)] + [InlineData(0, 273.15, 0, 150, 32, 0, 491.67)] + [InlineData(1, 276.18, 3.03, 145.45, 37.45, 2.42, 497.12)] + [InlineData(2, 279.21, 6.06, 140.91, 42.91, 4.85, 502.58)] + [InlineData(3, 282.24, 9.09, 136.36, 48.36, 7.27, 508.03)] + [InlineData(4, 285.27, 12.12, 131.82, 53.82, 9.7, 513.49)] + [InlineData(5, 288.3, 15.15, 127.27, 59.27, 12.12, 518.94)] + [InlineData(6, 291.33, 18.18, 122.73, 64.73, 14.55, 524.4)] + [InlineData(7, 294.36, 21.21, 118.18, 70.18, 16.97, 529.85)] + [InlineData(8, 297.39, 24.24, 113.64, 75.64, 19.39, 535.31)] + [InlineData(9, 300.42, 27.27, 109.09, 81.09, 21.82, 540.76)] + [InlineData(10, 303.45, 30.3, 104.55, 86.55, 24.24, 546.22)] + [InlineData(20, 333.76, 60.61, 59.09, 141.09, 48.48, 600.76)] + [InlineData(30, 364.06, 90.91, 13.64, 195.64, 72.73, 655.31)] + [InlineData(40, 394.36, 121.21, -31.82, 250.18, 96.97, 709.85)] + [InlineData(50, 424.67, 151.52, -77.27, 304.73, 121.21, 764.4)] + [InlineData(60, 454.97, 181.82, -122.73, 359.27, 145.45, 818.94)] + [InlineData(70, 485.27, 212.12, -168.18, 413.82, 169.7, 873.49)] + [InlineData(80, 515.57, 242.42, -213.64, 468.36, 193.94, 928.03)] + [InlineData(90, 545.88, 272.73, -259.09, 522.91, 218.18, 982.58)] + [InlineData(100, 576.18, 303.03, -304.55, 577.45, 242.42, 1037.12)] + [InlineData(1000, 3303.45, 3030.3, -4395.45, 5486.55, 2424.24, 5946.22)] + public void TemperatureFromNewtonShouldProduceTheExpectedConversionResults( + double newton, + double kelvin, + double celsius, + double delisle, + double fahrenheit, + double reaumur, + double rankine) + { + // Arrange / Act + Temperature temperature = Temperature.FromNewton(newton); + + // Assert + Assert.Equal(newton, Math.Round(temperature.Newton, 2)); + Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); + Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); + Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); + Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); + Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); + Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); + } + + [Theory(DisplayName = "Temperature.FromReaumur should produce the expected conversion results")] + [InlineData(-1000, -976.85, -1250, 2025, -2218, -412.5, -1758.33)] + [InlineData(-100, 148.15, -125, 337.5, -193, -41.25, 266.67)] + [InlineData(-90, 160.65, -112.5, 318.75, -170.5, -37.12, 289.17)] + [InlineData(-80, 173.15, -100, 300, -148, -33, 311.67)] + [InlineData(-70, 185.65, -87.5, 281.25, -125.5, -28.88, 334.17)] + [InlineData(-60, 198.15, -75, 262.5, -103, -24.75, 356.67)] + [InlineData(-50, 210.65, -62.5, 243.75, -80.5, -20.62, 379.17)] + [InlineData(-40, 223.15, -50, 225, -58, -16.5, 401.67)] + [InlineData(-30, 235.65, -37.5, 206.25, -35.5, -12.38, 424.17)] + [InlineData(-20, 248.15, -25, 187.5, -13, -8.25, 446.67)] + [InlineData(-10, 260.65, -12.5, 168.75, 9.5, -4.12, 469.17)] + [InlineData(-9, 261.9, -11.25, 166.88, 11.75, -3.71, 471.42)] + [InlineData(-8, 263.15, -10, 165, 14, -3.3, 473.67)] + [InlineData(-7, 264.4, -8.75, 163.12, 16.25, -2.89, 475.92)] + [InlineData(-6, 265.65, -7.5, 161.25, 18.5, -2.48, 478.17)] + [InlineData(-5, 266.9, -6.25, 159.38, 20.75, -2.06, 480.42)] + [InlineData(-4, 268.15, -5, 157.5, 23, -1.65, 482.67)] + [InlineData(-3, 269.4, -3.75, 155.62, 25.25, -1.24, 484.92)] + [InlineData(-2, 270.65, -2.5, 153.75, 27.5, -0.82, 487.17)] + [InlineData(-1, 271.9, -1.25, 151.88, 29.75, -0.41, 489.42)] + [InlineData(0, 273.15, 0, 150, 32, 0, 491.67)] + [InlineData(1, 274.4, 1.25, 148.12, 34.25, 0.41, 493.92)] + [InlineData(2, 275.65, 2.5, 146.25, 36.5, 0.82, 496.17)] + [InlineData(3, 276.9, 3.75, 144.38, 38.75, 1.24, 498.42)] + [InlineData(4, 278.15, 5, 142.5, 41, 1.65, 500.67)] + [InlineData(5, 279.4, 6.25, 140.62, 43.25, 2.06, 502.92)] + [InlineData(6, 280.65, 7.5, 138.75, 45.5, 2.48, 505.17)] + [InlineData(7, 281.9, 8.75, 136.88, 47.75, 2.89, 507.42)] + [InlineData(8, 283.15, 10, 135, 50, 3.3, 509.67)] + [InlineData(9, 284.4, 11.25, 133.12, 52.25, 3.71, 511.92)] + [InlineData(10, 285.65, 12.5, 131.25, 54.5, 4.12, 514.17)] + [InlineData(20, 298.15, 25, 112.5, 77, 8.25, 536.67)] + [InlineData(30, 310.65, 37.5, 93.75, 99.5, 12.38, 559.17)] + [InlineData(40, 323.15, 50, 75, 122, 16.5, 581.67)] + [InlineData(50, 335.65, 62.5, 56.25, 144.5, 20.62, 604.17)] + [InlineData(60, 348.15, 75, 37.5, 167, 24.75, 626.67)] + [InlineData(70, 360.65, 87.5, 18.75, 189.5, 28.88, 649.17)] + [InlineData(80, 373.15, 100, 0, 212, 33, 671.67)] + [InlineData(90, 385.65, 112.5, -18.75, 234.5, 37.12, 694.17)] + [InlineData(100, 398.15, 125, -37.5, 257, 41.25, 716.67)] + [InlineData(1000, 1523.15, 1250, -1725, 2282, 412.5, 2741.67)] + public void TemperatureFromReaumurShouldProduceTheExpectedConversionResults( + double reaumur, + double kelvin, + double celsius, + double delisle, + double fahrenheit, + double newton, + double rankine) + { + // Arrange / Act + Temperature temperature = Temperature.FromReaumur(reaumur); + + // Assert + Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); + Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); + Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); + Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); + Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); + Assert.Equal(newton, Math.Round(temperature.Newton, 2)); + Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); + } + + [Theory(DisplayName = "Temperature.FromRankine should produce the expected conversion results")] + [InlineData(-1000, -555.56, -828.71, 1393.06, -1459.67, -273.47, -662.96)] + [InlineData(-100, -55.56, -328.71, 643.06, -559.67, -108.47, -262.96)] + [InlineData(-90, -50, -323.15, 634.72, -549.67, -106.64, -258.52)] + [InlineData(-80, -44.44, -317.59, 626.39, -539.67, -104.81, -254.08)] + [InlineData(-70, -38.89, -312.04, 618.06, -529.67, -102.97, -249.63)] + [InlineData(-60, -33.33, -306.48, 609.72, -519.67, -101.14, -245.19)] + [InlineData(-50, -27.78, -300.93, 601.39, -509.67, -99.31, -240.74)] + [InlineData(-40, -22.22, -295.37, 593.06, -499.67, -97.47, -236.3)] + [InlineData(-30, -16.67, -289.82, 584.72, -489.67, -95.64, -231.85)] + [InlineData(-20, -11.11, -284.26, 576.39, -479.67, -93.81, -227.41)] + [InlineData(-10, -5.56, -278.71, 568.06, -469.67, -91.97, -222.96)] + [InlineData(-9, -5, -278.15, 567.22, -468.67, -91.79, -222.52)] + [InlineData(-8, -4.44, -277.59, 566.39, -467.67, -91.61, -222.08)] + [InlineData(-7, -3.89, -277.04, 565.56, -466.67, -91.42, -221.63)] + [InlineData(-6, -3.33, -276.48, 564.72, -465.67, -91.24, -221.19)] + [InlineData(-5, -2.78, -275.93, 563.89, -464.67, -91.06, -220.74)] + [InlineData(-4, -2.22, -275.37, 563.06, -463.67, -90.87, -220.3)] + [InlineData(-3, -1.67, -274.82, 562.22, -462.67, -90.69, -219.85)] + [InlineData(-2, -1.11, -274.26, 561.39, -461.67, -90.51, -219.41)] + [InlineData(-1, -0.56, -273.71, 560.56, -460.67, -90.32, -218.96)] + [InlineData(0, 0, -273.15, 559.72, -459.67, -90.14, -218.52)] + [InlineData(1, 0.56, -272.59, 558.89, -458.67, -89.96, -218.08)] + [InlineData(2, 1.11, -272.04, 558.06, -457.67, -89.77, -217.63)] + [InlineData(3, 1.67, -271.48, 557.22, -456.67, -89.59, -217.19)] + [InlineData(4, 2.22, -270.93, 556.39, -455.67, -89.41, -216.74)] + [InlineData(5, 2.78, -270.37, 555.56, -454.67, -89.22, -216.3)] + [InlineData(6, 3.33, -269.82, 554.72, -453.67, -89.04, -215.85)] + [InlineData(7, 3.89, -269.26, 553.89, -452.67, -88.86, -215.41)] + [InlineData(8, 4.44, -268.71, 553.06, -451.67, -88.67, -214.96)] + [InlineData(9, 5, -268.15, 552.22, -450.67, -88.49, -214.52)] + [InlineData(10, 5.56, -267.59, 551.39, -449.67, -88.31, -214.08)] + [InlineData(20, 11.11, -262.04, 543.06, -439.67, -86.47, -209.63)] + [InlineData(30, 16.67, -256.48, 534.72, -429.67, -84.64, -205.19)] + [InlineData(40, 22.22, -250.93, 526.39, -419.67, -82.81, -200.74)] + [InlineData(50, 27.78, -245.37, 518.06, -409.67, -80.97, -196.3)] + [InlineData(60, 33.33, -239.82, 509.72, -399.67, -79.14, -191.85)] + [InlineData(70, 38.89, -234.26, 501.39, -389.67, -77.31, -187.41)] + [InlineData(80, 44.44, -228.71, 493.06, -379.67, -75.47, -182.96)] + [InlineData(90, 50, -223.15, 484.72, -369.67, -73.64, -178.52)] + [InlineData(100, 55.56, -217.59, 476.39, -359.67, -71.81, -174.08)] + [InlineData(1000, 555.56, 282.41, -273.61, 540.33, 93.19, 225.92)] + public void TemperatureFromRankineShouldProduceTheExpectedConversionResults( + double rankine, + double kelvin, + double celsius, + double delisle, + double fahrenheit, + double newton, + double reaumur) + { + // Arrange / Act + Temperature temperature = Temperature.FromRankine(rankine); + + // Assert + Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); + Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); + Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); + Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); + Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); + Assert.Equal(newton, Math.Round(temperature.Newton, 2)); + Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); + } +} diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj index fe902d5..199dc2b 100644 --- a/OnixLabs.Core/OnixLabs.Core.csproj +++ b/OnixLabs.Core/OnixLabs.Core.csproj @@ -50,4 +50,5 @@ + diff --git a/OnixLabs.Core/Units/Temperature.Arithmetic.cs b/OnixLabs.Core/Units/Temperature.Arithmetic.cs new file mode 100644 index 0000000..e7e0576 --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.Arithmetic.cs @@ -0,0 +1,106 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Core.Units; + +public readonly partial struct Temperature +{ + /// + /// Computes the sum of the specified values. + /// + /// The left-hand value to add to. + /// The right-hand value to add. + /// Returns the sum of the specified values. + public static Temperature Add(Temperature left, Temperature right) + { + return new Temperature(left.Kelvin + right.Kelvin); + } + + /// + /// Computes the difference between the specified values. + /// + /// The left-hand value to subtract from. + /// The right-hand value to subtract. + /// Returns the difference between the specified values. + public static Temperature Subtract(Temperature left, Temperature right) + { + return new Temperature(left.Kelvin - right.Kelvin); + } + + /// + /// Computes the product of the specified values. + /// + /// The left-hand value to multiply. + /// The right-hand value to multiply by. + /// Returns the product of the specified values. + public static Temperature Multiply(Temperature left, Temperature right) + { + return new Temperature(left.Kelvin * right.Kelvin); + } + + /// + /// Computes the quotient of the specified values. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// Returns the quotient of the specified values. + public static Temperature Divide(Temperature left, Temperature right) + { + return new Temperature(left.Kelvin / right.Kelvin); + } + + /// + /// Computes the sum of the specified values. + /// + /// The left-hand value to add to. + /// The right-hand value to add. + /// Returns the sum of the specified values. + public static Temperature operator +(Temperature left, Temperature right) + { + return Add(left, right); + } + + /// + /// Computes the difference between the specified values. + /// + /// The left-hand value to subtract from. + /// The right-hand value to subtract. + /// Returns the difference between the specified values. + public static Temperature operator -(Temperature left, Temperature right) + { + return Subtract(left, right); + } + + /// + /// Computes the product of the specified values. + /// + /// The left-hand value to multiply. + /// The right-hand value to multiply by. + /// Returns the product of the specified values. + public static Temperature operator *(Temperature left, Temperature right) + { + return Multiply(left, right); + } + + /// + /// Computes the quotient of the specified values. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// Returns the quotient of the specified values. + public static Temperature operator /(Temperature left, Temperature right) + { + return Divide(left, right); + } +} diff --git a/OnixLabs.Core/Units/Temperature.Comparable.cs b/OnixLabs.Core/Units/Temperature.Comparable.cs new file mode 100644 index 0000000..6ac6d87 --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.Comparable.cs @@ -0,0 +1,100 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Units; + +public readonly partial struct Temperature : IComparable>, IComparable +{ + /// + /// Compares two values and returns an integer that indicates + /// whether the left-hand value is less than, equal to, or greater than the right-hand value. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns a value that indicates the relative order of the objects being compared. + public static int Compare(Temperature left, Temperature right) + { + return left.Kelvin.CompareTo(right.Kelvin); + } + + /// + /// Compares the current instance with another object of the same type and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other object. + /// + /// An object to compare with this instance. + /// Returns a value that indicates the relative order of the objects being compared. + public int CompareTo(Temperature other) + { + return Compare(this, other); + } + + /// + /// Compares the current instance with another object of the same type and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other object. + /// + /// An object to compare with this instance. + /// Returns a value that indicates the relative order of the objects being compared. + public int CompareTo(object? obj) + { + return this.CompareObject(obj); + } + + /// + /// Performs a greater than comparison check between two values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the left-hand operand is greater than right-hand operand; otherwise, false. + public static bool operator >(Temperature left, Temperature right) + { + return Compare(left, right) is 1; + } + + /// + /// Performs a greater than or equal comparison check between two values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the left-hand operand is greater than or equal to right-hand operand; otherwise, false. + public static bool operator >=(Temperature left, Temperature right) + { + return Compare(left, right) is 1 or 0; + } + + /// + /// Performs a less than comparison check between two values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the left-hand operand is less than right-hand operand; otherwise, false. + public static bool operator <(Temperature left, Temperature right) + { + return Compare(left, right) is -1; + } + + /// + /// Performs a less than or equal comparison check between two values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the left-hand operand is less than or equal to right-hand operand; otherwise, false. + public static bool operator <=(Temperature left, Temperature right) + { + return Compare(left, right) is -1 or 0; + } +} diff --git a/OnixLabs.Core/Units/Temperature.Constants.cs b/OnixLabs.Core/Units/Temperature.Constants.cs new file mode 100644 index 0000000..fac061d --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.Constants.cs @@ -0,0 +1,28 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Core.Units; + +public readonly partial struct Temperature +{ + /// + /// Represents an absolute zero (0°K) value. + /// + public static Temperature Zero => default; + + /// + /// Gets the default format. + /// + private const string DefaultFormat = "K"; +} diff --git a/OnixLabs.Core/Units/Temperature.Equatable.cs b/OnixLabs.Core/Units/Temperature.Equatable.cs new file mode 100644 index 0000000..44ec236 --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.Equatable.cs @@ -0,0 +1,82 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Units; + +public readonly partial struct Temperature : IEquatable> +{ + /// + /// Compares two instances of to determine whether their values are equal. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool Equals(Temperature left, Temperature right) + { + return left.Kelvin == right.Kelvin; + } + + /// + /// Indicates whether the current object is equal to another object of the same type. + /// + /// An object to compare with this object. + /// Returns true if the current object is equal to the other parameter; otherwise, false. + public bool Equals(Temperature other) + { + return Equals(this, other); + } + + /// + /// Checks for equality between this instance and another object. + /// + /// The object to check for equality. + /// true if the object is equal to this instance; otherwise, false. + public override bool Equals(object? obj) + { + return obj is Temperature other && Equals(other); + } + + /// + /// Serves as a hash code function for this instance. + /// + /// A hash code for this instance. + public override int GetHashCode() + { + return HashCode.Combine(Kelvin); + } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(Temperature left, Temperature right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(Temperature left, Temperature right) + { + return !Equals(left, right); + } +} diff --git a/OnixLabs.Core/Units/Temperature.From.cs b/OnixLabs.Core/Units/Temperature.From.cs new file mode 100644 index 0000000..5be9b19 --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.From.cs @@ -0,0 +1,88 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Core.Units; + +public readonly partial struct Temperature +{ + /// + /// Creates a new instance from the specified Celsius value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified Celsius value. + public static Temperature FromCelsius(T value) + { + return new Temperature(value + T.CreateChecked(273.15)); + } + + /// + /// Creates a new instance from the specified Delisle value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified Delisle value. + public static Temperature FromDelisle(T value) + { + return new Temperature(T.CreateChecked(373.15) - value * T.CreateChecked(2) / T.CreateChecked(3)); + } + + /// + /// Creates a new instance from the specified Fahrenheit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified Fahrenheit value. + public static Temperature FromFahrenheit(T value) + { + return new Temperature((value + T.CreateChecked(459.67)) * T.CreateChecked(5) / T.CreateChecked(9)); + } + + /// + /// Creates a new instance from the specified Kelvin value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified Kelvin value. + public static Temperature FromKelvin(T value) + { + return new Temperature(value); + } + + /// + /// Creates a new instance from the specified Newton value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified Newton value. + public static Temperature FromNewton(T value) + { + return new Temperature(value * (T.CreateChecked(100) / T.CreateChecked(33)) + T.CreateChecked(273.15)); + } + + /// + /// Creates a new instance from the specified Reaumur value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified Reaumur value. + public static Temperature FromReaumur(T value) + { + return new Temperature(value * T.CreateChecked(1.25) + T.CreateChecked(273.15)); + } + + /// + /// Creates a new instance from the specified Rankine value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified Rankine value. + public static Temperature FromRankine(T value) + { + return new Temperature(value / T.CreateChecked(1.8)); + } +} diff --git a/OnixLabs.Core/Units/Temperature.Static.Arithmetic.cs b/OnixLabs.Core/Units/Temperature.Static.Arithmetic.cs new file mode 100644 index 0000000..715e13b --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.Static.Arithmetic.cs @@ -0,0 +1,71 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.Units; + +/// +/// Provides functionality for managing instances. +/// +public static partial class Temperature +{ + /// + /// Computes the sum of the specified values. + /// + /// The left-hand value to add to. + /// The right-hand value to add. + /// The underlying type that represents the unit. + /// Returns the sum of the specified values. + public static Temperature Add(Temperature left, Temperature right) where T : IFloatingPoint + { + return Temperature.Add(left, right); + } + + /// + /// Computes the difference between the specified values. + /// + /// The left-hand value to subtract from. + /// The right-hand value to subtract. + /// The underlying type that represents the unit. + /// Returns the difference between the specified values. + public static Temperature Subtract(Temperature left, Temperature right) where T : IFloatingPoint + { + return Temperature.Subtract(left, right); + } + + /// + /// Computes the product of the specified values. + /// + /// The left-hand value to multiply. + /// The right-hand value to multiply by. + /// The underlying type that represents the unit. + /// Returns the product of the specified values. + public static Temperature Multiply(Temperature left, Temperature right) where T : IFloatingPoint + { + return Temperature.Multiply(left, right); + } + + /// + /// Computes the quotient of the specified values. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// The underlying type that represents the unit. + /// Returns the quotient of the specified values. + public static Temperature Divide(Temperature left, Temperature right) where T : IFloatingPoint + { + return Temperature.Divide(left, right); + } +} diff --git a/OnixLabs.Core/Units/Temperature.Static.Comparison.cs b/OnixLabs.Core/Units/Temperature.Static.Comparison.cs new file mode 100644 index 0000000..1985987 --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.Static.Comparison.cs @@ -0,0 +1,45 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.Units; + +public static partial class Temperature +{ + /// + /// Compares two values and returns an integer that indicates + /// whether the left-hand value is less than, equal to, or greater than the right-hand value. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// The underlying type that represents the unit. + /// Returns a value that indicates the relative order of the objects being compared. + public static int Compare(Temperature left, Temperature right) where T : IFloatingPoint + { + return Temperature.Compare(left, right); + } + + /// + /// Compares two instances of to determine whether their values are equal. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// The underlying type that represents the unit. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool Equals(Temperature left, Temperature right) where T : IFloatingPoint + { + return Temperature.Equals(left, right); + } +} diff --git a/OnixLabs.Core/Units/Temperature.Static.From.cs b/OnixLabs.Core/Units/Temperature.Static.From.cs new file mode 100644 index 0000000..aa5f7e2 --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.Static.From.cs @@ -0,0 +1,97 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.Units; + +public static partial class Temperature +{ + /// + /// Creates a new instance from the specified Celsius value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified Celsius value. + public static Temperature FromCelsius(T value) where T : IFloatingPoint + { + return Temperature.FromCelsius(value); + } + + /// + /// Creates a new instance from the specified Delisle value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified Delisle value. + public static Temperature FromDelisle(T value) where T : IFloatingPoint + { + return Temperature.FromDelisle(value); + } + + /// + /// Creates a new instance from the specified Fahrenheit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified Fahrenheit value. + public static Temperature FromFahrenheit(T value) where T : IFloatingPoint + { + return Temperature.FromFahrenheit(value); + } + + /// + /// Creates a new instance from the specified Kelvin value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified Kelvin value. + public static Temperature FromKelvin(T value) where T : IFloatingPoint + { + return Temperature.FromKelvin(value); + } + + /// + /// Creates a new instance from the specified Newton value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified Newton value. + public static Temperature FromNewton(T value) where T : IFloatingPoint + { + return Temperature.FromNewton(value); + } + + /// + /// Creates a new instance from the specified Reaumur value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified Reaumur value. + public static Temperature FromReaumur(T value) where T : IFloatingPoint + { + return Temperature.FromReaumur(value); + } + + /// + /// Creates a new instance from the specified Rankine value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified Rankine value. + public static Temperature FromRankine(T value) where T : IFloatingPoint + { + return Temperature.FromRankine(value); + } +} diff --git a/OnixLabs.Core/Units/Temperature.To.cs b/OnixLabs.Core/Units/Temperature.To.cs new file mode 100644 index 0000000..ff73a05 --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.To.cs @@ -0,0 +1,65 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; + +namespace OnixLabs.Core.Units; + +public readonly partial struct Temperature : IFormattable +{ + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(string? format, IFormatProvider? formatProvider = null) + { + (string formatOrDefault, T value) = (format ?? DefaultFormat).ToUpper() switch + { + "K" => ("K", Kelvin), + "C" => ("C", Celsius), + "D" => ("D", Delisle), + "F" => ("F", Fahrenheit), + "N" => ("N", Newton), + "R" => ("R", Reaumur), + "RA" => ("Ra", Rankine), + _ => throw new ArgumentException($"Invalid format specifier: {format}") + }; + + string number = value.ToString("R", formatProvider as CultureInfo ?? CultureInfo.CurrentCulture); + return $"{number}°{formatOrDefault}"; + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + { + return ToString(format.ToString(), formatProvider); + } + + /// + /// Formats the value of the current instance using the default format. + /// + /// The value of the current instance in the default format. + public override string ToString() + { + return ToString(DefaultFormat, CultureInfo.CurrentCulture); + } +} diff --git a/OnixLabs.Core/Units/Temperature.cs b/OnixLabs.Core/Units/Temperature.cs new file mode 100644 index 0000000..1b1d516 --- /dev/null +++ b/OnixLabs.Core/Units/Temperature.cs @@ -0,0 +1,68 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.Units; + +/// +/// Represents a unit of temperature. +/// +/// The underlying type that represents the current unit. +public readonly partial struct Temperature where T : IFloatingPoint +{ + /// + /// Initializes a new instance of the struct. + /// + /// The initial temperature value in Kelvin. + private Temperature(T kelvin) + { + Kelvin = kelvin; + } + + /// + /// Gets the current in Kelvin. + /// + public T Kelvin { get; } + + /// + /// Gets the current in Celsius. + /// + public T Celsius => Kelvin - T.CreateChecked(273.15); + + /// + /// Gets the current in Delisle. + /// + public T Delisle => (T.CreateChecked(373.15) - Kelvin) * T.CreateChecked(1.5); + + /// + /// Gets the current in Fahrenheit. + /// + public T Fahrenheit => Kelvin * T.CreateChecked(1.8) - T.CreateChecked(459.67); + + /// + /// Gets the current in Newton. + /// + public T Newton => (Kelvin - T.CreateChecked(273.15)) * T.CreateChecked(0.33); + + /// + /// Gets the current in Reaumur. + /// + public T Reaumur => (Kelvin - T.CreateChecked(273.15)) * T.CreateChecked(0.8); + + /// + /// Gets the current in Rankine. + /// + public T Rankine => Kelvin * T.CreateChecked(1.8); +} From 30250bd716937bc4b9a5a6740140daab905d5450 Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Sun, 12 Nov 2023 00:27:14 +0000 Subject: [PATCH 06/14] Added DataSize implementation (#31) --- .../Units/DataSizeTests.cs | 835 ++++++++++++++++++ OnixLabs.Core/Numerics/GenericMath.cs | 43 + OnixLabs.Core/OnixLabs.Core.csproj | 1 + OnixLabs.Core/Units/DataSize.Arithmetic.cs | 106 +++ OnixLabs.Core/Units/DataSize.Comparable.cs | 100 +++ OnixLabs.Core/Units/DataSize.Constants.cs | 63 ++ OnixLabs.Core/Units/DataSize.Equatable.cs | 82 ++ OnixLabs.Core/Units/DataSize.From.cs | 424 +++++++++ .../Units/DataSize.Static.Arithmetic.cs | 71 ++ .../Units/DataSize.Static.Comparison.cs | 45 + OnixLabs.Core/Units/DataSize.Static.From.cs | 438 +++++++++ OnixLabs.Core/Units/DataSize.To.cs | 185 ++++ OnixLabs.Core/Units/DataSize.cs | 247 ++++++ OnixLabs.Core/Units/Temperature.To.cs | 57 +- OnixLabs.Playground/Program.cs | 5 + 15 files changed, 2687 insertions(+), 15 deletions(-) create mode 100644 OnixLabs.Core.UnitTests/Units/DataSizeTests.cs create mode 100644 OnixLabs.Core/Numerics/GenericMath.cs create mode 100644 OnixLabs.Core/Units/DataSize.Arithmetic.cs create mode 100644 OnixLabs.Core/Units/DataSize.Comparable.cs create mode 100644 OnixLabs.Core/Units/DataSize.Constants.cs create mode 100644 OnixLabs.Core/Units/DataSize.Equatable.cs create mode 100644 OnixLabs.Core/Units/DataSize.From.cs create mode 100644 OnixLabs.Core/Units/DataSize.Static.Arithmetic.cs create mode 100644 OnixLabs.Core/Units/DataSize.Static.Comparison.cs create mode 100644 OnixLabs.Core/Units/DataSize.Static.From.cs create mode 100644 OnixLabs.Core/Units/DataSize.To.cs create mode 100644 OnixLabs.Core/Units/DataSize.cs diff --git a/OnixLabs.Core.UnitTests/Units/DataSizeTests.cs b/OnixLabs.Core.UnitTests/Units/DataSizeTests.cs new file mode 100644 index 0000000..9e5f1b7 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Units/DataSizeTests.cs @@ -0,0 +1,835 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Core.Units; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Units; + +public sealed class DataSizeTests +{ + [Theory(DisplayName = "DataSize.FromNibbles should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 4)] + [InlineData(2, 8)] + [InlineData(3, 12)] + [InlineData(4, 16)] + [InlineData(5, 20)] + [InlineData(6, 24)] + [InlineData(7, 28)] + [InlineData(8, 32)] + [InlineData(9, 36)] + [InlineData(10, 40)] + public void DataSizeFromNibblesShouldProduceTheExpectedConversionResults(double nibbles, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromNibbles(nibbles); + + // Assert + Assert.Equal(nibbles, dataSize.Nibbles); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8)] + [InlineData(2, 16)] + [InlineData(3, 24)] + [InlineData(4, 32)] + [InlineData(5, 40)] + [InlineData(6, 48)] + [InlineData(7, 56)] + [InlineData(8, 64)] + [InlineData(9, 72)] + [InlineData(10, 80)] + public void DataSizeFromBytesShouldProduceTheExpectedConversionResults(double bytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromBytes(bytes); + + // Assert + Assert.Equal(bytes, dataSize.Bytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromWords should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 16)] + [InlineData(2, 32)] + [InlineData(3, 48)] + [InlineData(4, 64)] + [InlineData(5, 80)] + [InlineData(6, 96)] + [InlineData(7, 112)] + [InlineData(8, 128)] + [InlineData(9, 144)] + [InlineData(10, 160)] + public void DataSizeFromWordsShouldProduceTheExpectedConversionResults(double words, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromWords(words); + + // Assert + Assert.Equal(words, dataSize.Words); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromDoubleWords should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 32)] + [InlineData(2, 64)] + [InlineData(3, 96)] + [InlineData(4, 128)] + [InlineData(5, 160)] + [InlineData(6, 192)] + [InlineData(7, 224)] + [InlineData(8, 256)] + [InlineData(9, 288)] + [InlineData(10, 320)] + public void DataSizeFromDoubleWordsShouldProduceTheExpectedConversionResults(double doubleWords, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromDoubleWords(doubleWords); + + // Assert + Assert.Equal(doubleWords, dataSize.DoubleWords); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromQuadWords should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 64)] + [InlineData(2, 128)] + [InlineData(3, 192)] + [InlineData(4, 256)] + [InlineData(5, 320)] + [InlineData(6, 384)] + [InlineData(7, 448)] + [InlineData(8, 512)] + [InlineData(9, 576)] + [InlineData(10, 640)] + public void DataSizeFromQuadWordsShouldProduceTheExpectedConversionResults(double quadWords, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromQuadWords(quadWords); + + // Assert + Assert.Equal(quadWords, dataSize.QuadWords); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromKiloBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1000)] + [InlineData(2, 2000)] + [InlineData(3, 3000)] + [InlineData(4, 4000)] + [InlineData(5, 5000)] + [InlineData(6, 6000)] + [InlineData(7, 7000)] + [InlineData(8, 8000)] + [InlineData(9, 9000)] + [InlineData(10, 10000)] + public void DataSizeFromKiloBitsShouldProduceTheExpectedConversionResults(double kiloBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromKiloBits(kiloBits); + + // Assert + Assert.Equal(kiloBits, dataSize.KiloBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromKibiBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1024)] + [InlineData(2, 2048)] + [InlineData(3, 3072)] + [InlineData(4, 4096)] + [InlineData(5, 5120)] + [InlineData(6, 6144)] + [InlineData(7, 7168)] + [InlineData(8, 8192)] + [InlineData(9, 9216)] + [InlineData(10, 10240)] + public void DataSizeFromKibiBitsShouldProduceTheExpectedConversionResults(double kibiBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromKibiBits(kibiBits); + + // Assert + Assert.Equal(kibiBits, dataSize.KibiBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromKiloBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8000)] + [InlineData(2, 16000)] + [InlineData(3, 24000)] + [InlineData(4, 32000)] + [InlineData(5, 40000)] + [InlineData(6, 48000)] + [InlineData(7, 56000)] + [InlineData(8, 64000)] + [InlineData(9, 72000)] + [InlineData(10, 80000)] + public void DataSizeFromKiloBytesShouldProduceTheExpectedConversionResults(double kiloBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromKiloBytes(kiloBytes); + + // Assert + Assert.Equal(kiloBytes, dataSize.KiloBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromKibiBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8192)] + [InlineData(2, 16384)] + [InlineData(3, 24576)] + [InlineData(4, 32768)] + [InlineData(5, 40960)] + [InlineData(6, 49152)] + [InlineData(7, 57344)] + [InlineData(8, 65536)] + [InlineData(9, 73728)] + [InlineData(10, 81920)] + public void DataSizeFromKibiBytesShouldProduceTheExpectedConversionResults(double kibiBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromKibiBytes(kibiBytes); + + // Assert + Assert.Equal(kibiBytes, dataSize.KibiBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromMegaBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1000000)] + [InlineData(2, 2000000)] + [InlineData(3, 3000000)] + [InlineData(4, 4000000)] + [InlineData(5, 5000000)] + [InlineData(6, 6000000)] + [InlineData(7, 7000000)] + [InlineData(8, 8000000)] + [InlineData(9, 9000000)] + [InlineData(10, 10000000)] + public void DataSizeFromMegaBitsShouldProduceTheExpectedConversionResults(double megaBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromMegaBits(megaBits); + + // Assert + Assert.Equal(megaBits, dataSize.MegaBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromMebiBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1048576)] + [InlineData(2, 2097152)] + [InlineData(3, 3145728)] + [InlineData(4, 4194304)] + [InlineData(5, 5242880)] + [InlineData(6, 6291456)] + [InlineData(7, 7340032)] + [InlineData(8, 8388608)] + [InlineData(9, 9437184)] + [InlineData(10, 10485760)] + public void DataSizeFromMebiBitsShouldProduceTheExpectedConversionResults(double mebiBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromMebiBits(mebiBits); + + // Assert + Assert.Equal(mebiBits, dataSize.MebiBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromMegaBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8000000)] + [InlineData(2, 16000000)] + [InlineData(3, 24000000)] + [InlineData(4, 32000000)] + [InlineData(5, 40000000)] + [InlineData(6, 48000000)] + [InlineData(7, 56000000)] + [InlineData(8, 64000000)] + [InlineData(9, 72000000)] + [InlineData(10, 80000000)] + public void DataSizeFromMegaBytesShouldProduceTheExpectedConversionResults(double megaBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromMegaBytes(megaBytes); + + // Assert + Assert.Equal(megaBytes, dataSize.MegaBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromMebiBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8388608)] + [InlineData(2, 16777216)] + [InlineData(3, 25165824)] + [InlineData(4, 33554432)] + [InlineData(5, 41943040)] + [InlineData(6, 50331648)] + [InlineData(7, 58720256)] + [InlineData(8, 67108864)] + [InlineData(9, 75497472)] + [InlineData(10, 83886080)] + public void DataSizeFromMebiBytesShouldProduceTheExpectedConversionResults(double mebiBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromMebiBytes(mebiBytes); + + // Assert + Assert.Equal(mebiBytes, dataSize.MebiBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromGigaBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1000000000)] + [InlineData(2, 2000000000)] + [InlineData(3, 3000000000)] + [InlineData(4, 4000000000)] + [InlineData(5, 5000000000)] + [InlineData(6, 6000000000)] + [InlineData(7, 7000000000)] + [InlineData(8, 8000000000)] + [InlineData(9, 9000000000)] + [InlineData(10, 10000000000)] + public void DataSizeFromGigaBitsShouldProduceTheExpectedConversionResults(double gigaBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromGigaBits(gigaBits); + + // Assert + Assert.Equal(gigaBits, dataSize.GigaBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromGibiBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1073741824)] + [InlineData(2, 2147483648)] + [InlineData(3, 3221225472)] + [InlineData(4, 4294967296)] + [InlineData(5, 5368709120)] + [InlineData(6, 6442450944)] + [InlineData(7, 7516192768)] + [InlineData(8, 8589934592)] + [InlineData(9, 9663676416)] + [InlineData(10, 10737418240)] + public void DataSizeFromGibiBitsShouldProduceTheExpectedConversionResults(double gibiBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromGibiBits(gibiBits); + + // Assert + Assert.Equal(gibiBits, dataSize.GibiBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromGigaBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8000000000)] + [InlineData(2, 16000000000)] + [InlineData(3, 24000000000)] + [InlineData(4, 32000000000)] + [InlineData(5, 40000000000)] + [InlineData(6, 48000000000)] + [InlineData(7, 56000000000)] + [InlineData(8, 64000000000)] + [InlineData(9, 72000000000)] + [InlineData(10, 80000000000)] + public void DataSizeFromGigaBytesShouldProduceTheExpectedConversionResults(double gigaBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromGigaBytes(gigaBytes); + + // Assert + Assert.Equal(gigaBytes, dataSize.GigaBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromGibiBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8589934592)] + [InlineData(2, 17179869184)] + [InlineData(3, 25769803776)] + [InlineData(4, 34359738368)] + [InlineData(5, 42949672960)] + [InlineData(6, 51539607552)] + [InlineData(7, 60129542144)] + [InlineData(8, 68719476736)] + [InlineData(9, 77309411328)] + [InlineData(10, 85899345920)] + public void DataSizeFromGibiBytesShouldProduceTheExpectedConversionResults(double gibiBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromGibiBytes(gibiBytes); + + // Assert + Assert.Equal(gibiBytes, dataSize.GibiBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromTeraBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1000000000000)] + [InlineData(2, 2000000000000)] + [InlineData(3, 3000000000000)] + [InlineData(4, 4000000000000)] + [InlineData(5, 5000000000000)] + [InlineData(6, 6000000000000)] + [InlineData(7, 7000000000000)] + [InlineData(8, 8000000000000)] + [InlineData(9, 9000000000000)] + [InlineData(10, 10000000000000)] + public void DataSizeFromTeraBitsShouldProduceTheExpectedConversionResults(double teraBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromTeraBits(teraBits); + + // Assert + Assert.Equal(teraBits, dataSize.TeraBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromTebiBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1099511627776)] + [InlineData(2, 2199023255552)] + [InlineData(3, 3298534883328)] + [InlineData(4, 4398046511104)] + [InlineData(5, 5497558138880)] + [InlineData(6, 6597069766656)] + [InlineData(7, 7696581394432)] + [InlineData(8, 8796093022208)] + [InlineData(9, 9895604649984)] + [InlineData(10, 10995116277760)] + public void DataSizeFromTebiBitsShouldProduceTheExpectedConversionResults(double tebiBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromTebiBits(tebiBits); + + // Assert + Assert.Equal(tebiBits, dataSize.TebiBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromTeraBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8000000000000)] + [InlineData(2, 16000000000000)] + [InlineData(3, 24000000000000)] + [InlineData(4, 32000000000000)] + [InlineData(5, 40000000000000)] + [InlineData(6, 48000000000000)] + [InlineData(7, 56000000000000)] + [InlineData(8, 64000000000000)] + [InlineData(9, 72000000000000)] + [InlineData(10, 80000000000000)] + public void DataSizeFromTeraBytesShouldProduceTheExpectedConversionResults(double teraBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromTeraBytes(teraBytes); + + // Assert + Assert.Equal(teraBytes, dataSize.TeraBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromTebiBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8796093022208)] + [InlineData(2, 17592186044416)] + [InlineData(3, 26388279066624)] + [InlineData(4, 35184372088832)] + [InlineData(5, 43980465111040)] + [InlineData(6, 52776558133248)] + [InlineData(7, 61572651155456)] + [InlineData(8, 70368744177664)] + [InlineData(9, 79164837199872)] + [InlineData(10, 87960930222080)] + public void DataSizeFromTebiBytesShouldProduceTheExpectedConversionResults(double tebiBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromTebiBytes(tebiBytes); + + // Assert + Assert.Equal(tebiBytes, dataSize.TebiBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromPetaBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1000000000000000)] + [InlineData(2, 2000000000000000)] + [InlineData(3, 3000000000000000)] + [InlineData(4, 4000000000000000)] + [InlineData(5, 5000000000000000)] + [InlineData(6, 6000000000000000)] + [InlineData(7, 7000000000000000)] + [InlineData(8, 8000000000000000)] + [InlineData(9, 9000000000000000)] + [InlineData(10, 10000000000000000)] + public void DataSizeFromPetaBitsShouldProduceTheExpectedConversionResults(double petaBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromPetaBits(petaBits); + + // Assert + Assert.Equal(petaBits, dataSize.PetaBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromPebiBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1125899906842624)] + [InlineData(2, 2251799813685248)] + [InlineData(3, 3377699720527872)] + [InlineData(4, 4503599627370496)] + [InlineData(5, 5629499534213120)] + [InlineData(6, 6755399441055744)] + [InlineData(7, 7881299347898368)] + [InlineData(8, 9007199254740992)] + [InlineData(9, 10133099161583616)] + [InlineData(10, 11258999068426240)] + public void DataSizeFromPebiBitsShouldProduceTheExpectedConversionResults(double pebiBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromPebiBits(pebiBits); + + // Assert + Assert.Equal(pebiBits, dataSize.PebiBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromPetaBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8000000000000000)] + [InlineData(2, 16000000000000000)] + [InlineData(3, 24000000000000000)] + [InlineData(4, 32000000000000000)] + [InlineData(5, 40000000000000000)] + [InlineData(6, 48000000000000000)] + [InlineData(7, 56000000000000000)] + [InlineData(8, 64000000000000000)] + [InlineData(9, 72000000000000000)] + [InlineData(10, 80000000000000000)] + public void DataSizeFromPetaBytesShouldProduceTheExpectedConversionResults(double petaBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromPetaBytes(petaBytes); + + // Assert + Assert.Equal(petaBytes, dataSize.PetaBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromPebiBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 9007199254740992)] + [InlineData(2, 18014398509481984)] + [InlineData(3, 27021597764222976)] + [InlineData(4, 36028797018963970)] + [InlineData(5, 45035996273704960)] + [InlineData(6, 54043195528445950)] + [InlineData(7, 63050394783186940)] + [InlineData(8, 72057594037927940)] + [InlineData(9, 81064793292668930)] + [InlineData(10, 90071992547409920)] + public void DataSizeFromPebiBytesShouldProduceTheExpectedConversionResults(double pebiBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromPebiBytes(pebiBytes); + + // Assert + Assert.Equal(pebiBytes, dataSize.PebiBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromExaBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1E+18)] + [InlineData(2, 2E+18)] + [InlineData(3, 3E+18)] + [InlineData(4, 4E+18)] + [InlineData(5, 5E+18)] + [InlineData(6, 6E+18)] + [InlineData(7, 7E+18)] + [InlineData(8, 8E+18)] + [InlineData(9, 9E+18)] + [InlineData(10, 1E+19)] + public void DataSizeFromExaBitsShouldProduceTheExpectedConversionResults(double exaBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromExaBits(exaBits); + + // Assert + Assert.Equal(exaBits, dataSize.ExaBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromExbiBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1.152921504606847E+18)] + [InlineData(2, 2.305843009213694E+18)] + [InlineData(3, 3.458764513820541E+18)] + [InlineData(4, 4.611686018427388E+18)] + [InlineData(5, 5.764607523034235E+18)] + [InlineData(6, 6.917529027641082E+18)] + [InlineData(7, 8.070450532247929E+18)] + [InlineData(8, 9.223372036854776E+18)] + [InlineData(9, 1.0376293541461623E+19)] + [InlineData(10, 1.152921504606847E+19)] + public void DataSizeFromExbiBitsShouldProduceTheExpectedConversionResults(double exbiBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromExbiBits(exbiBits); + + // Assert + Assert.Equal(exbiBits, dataSize.ExbiBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromExaBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8E+18)] + [InlineData(2, 1.6E+19)] + [InlineData(3, 2.4E+19)] + [InlineData(4, 3.2E+19)] + [InlineData(5, 4E+19)] + [InlineData(6, 4.8E+19)] + [InlineData(7, 5.6E+19)] + [InlineData(8, 6.4E+19)] + [InlineData(9, 7.2E+19)] + [InlineData(10, 8E+19)] + public void DataSizeFromExaBytesShouldProduceTheExpectedConversionResults(double exaBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromExaBytes(exaBytes); + + // Assert + Assert.Equal(exaBytes, dataSize.ExaBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromExbiBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 9.223372036854776E+18)] + [InlineData(2, 1.8446744073709552E+19)] + [InlineData(3, 2.7670116110564327E+19)] + [InlineData(4, 3.6893488147419103E+19)] + [InlineData(5, 4.611686018427388E+19)] + [InlineData(6, 5.5340232221128655E+19)] + [InlineData(7, 6.456360425798343E+19)] + [InlineData(8, 7.378697629483821E+19)] + [InlineData(9, 8.301034833169298E+19)] + [InlineData(10, 9.223372036854776E+19)] + public void DataSizeFromExbiBytesShouldProduceTheExpectedConversionResults(double exbiBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromExbiBytes(exbiBytes); + + // Assert + Assert.Equal(exbiBytes, dataSize.ExbiBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromZettaBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1E+21)] + [InlineData(2, 2E+21)] + [InlineData(3, 3E+21)] + [InlineData(4, 4E+21)] + [InlineData(5, 5E+21)] + [InlineData(6, 6E+21)] + [InlineData(7, 7E+21)] + [InlineData(8, 8E+21)] + [InlineData(9, 9E+21)] + [InlineData(10, 1E+22)] + public void DataSizeFromZettaBitsShouldProduceTheExpectedConversionResults(double zettaBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromZettaBits(zettaBits); + + // Assert + Assert.Equal(zettaBits, dataSize.ZettaBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromZebiBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1.1805916207174113E+21)] + [InlineData(2, 2.3611832414348226E+21)] + [InlineData(3, 3.541774862152234E+21)] + [InlineData(4, 4.722366482869645E+21)] + [InlineData(5, 5.902958103587057E+21)] + [InlineData(6, 7.083549724304468E+21)] + [InlineData(7, 8.264141345021879E+21)] + [InlineData(8, 9.44473296573929E+21)] + [InlineData(9, 1.0625324586456702E+22)] + [InlineData(10, 1.1805916207174113E+22)] + public void DataSizeFromZebiBitsShouldProduceTheExpectedConversionResults(double zebiBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromZebiBits(zebiBits); + + // Assert + Assert.Equal(zebiBits, dataSize.ZebiBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromZettaBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8E+21)] + [InlineData(2, 1.6E+22)] + [InlineData(3, 2.4E+22)] + [InlineData(4, 3.2E+22)] + [InlineData(5, 4E+22)] + [InlineData(6, 4.8E+22)] + [InlineData(7, 5.6E+22)] + [InlineData(8, 6.4E+22)] + [InlineData(9, 7.2E+22)] + [InlineData(10, 8E+22)] + public void DataSizeFromZettaBytesShouldProduceTheExpectedConversionResults(double zettaBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromZettaBytes(zettaBytes); + + // Assert + Assert.Equal(zettaBytes, dataSize.ZettaBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromZebiBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 9.44473296573929E+21)] + [InlineData(2, 1.888946593147858E+22)] + [InlineData(3, 2.833419889721787E+22)] + [InlineData(4, 3.777893186295716E+22)] + [InlineData(5, 4.722366482869645E+22)] + [InlineData(6, 5.666839779443574E+22)] + [InlineData(7, 6.611313076017503E+22)] + [InlineData(8, 7.555786372591432E+22)] + [InlineData(9, 8.500259669165361E+22)] + [InlineData(10, 9.44473296573929E+22)] + public void DataSizeFromZebiBytesShouldProduceTheExpectedConversionResults(double zebiBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromZebiBytes(zebiBytes); + + // Assert + Assert.Equal(zebiBytes, dataSize.ZebiBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromYottaBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1E+24)] + [InlineData(2, 2E+24)] + [InlineData(3, 3E+24)] + [InlineData(4, 4E+24)] + [InlineData(4.999999999999999, 4.999999999999999E+24)] + [InlineData(6, 6E+24)] + [InlineData(7.000000000000001, 7E+24)] + [InlineData(8, 8E+24)] + [InlineData(9, 8.999999999999999E+24)] + [InlineData(9.999999999999998, 9.999999999999999E+24)] + public void DataSizeFromYottaBitsShouldProduceTheExpectedConversionResults(double yottaBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromYottaBits(yottaBits); + + // Assert + Assert.Equal(yottaBits, dataSize.YottaBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromYobiBits should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 1.2089258196146292E+24)] + [InlineData(2, 2.4178516392292583E+24)] + [InlineData(3, 3.6267774588438875E+24)] + [InlineData(4, 4.835703278458517E+24)] + [InlineData(5, 6.044629098073146E+24)] + [InlineData(6, 7.253554917687775E+24)] + [InlineData(7, 8.462480737302404E+24)] + [InlineData(8, 9.671406556917033E+24)] + [InlineData(9, 1.0880332376531663E+25)] + [InlineData(10, 1.2089258196146292E+25)] + public void DataSizeFromYobiBitsShouldProduceTheExpectedConversionResults(double yobiBits, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromYobiBits(yobiBits); + + // Assert + Assert.Equal(yobiBits, dataSize.YobiBits); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromYottaBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 8E+24)] + [InlineData(2, 1.6E+25)] + [InlineData(3, 2.4E+25)] + [InlineData(4, 3.2E+25)] + [InlineData(4.999999999999999, 3.9999999999999995E+25)] + [InlineData(6, 4.8E+25)] + [InlineData(7.000000000000001, 5.6E+25)] + [InlineData(8, 6.4E+25)] + [InlineData(9, 7.1999999999999994E+25)] + [InlineData(9.999999999999998, 7.999999999999999E+25)] + public void DataSizeFromYottaBytesShouldProduceTheExpectedConversionResults(double yottaBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromYottaBytes(yottaBytes); + + // Assert + Assert.Equal(yottaBytes, dataSize.YottaBytes); + Assert.Equal(bits, dataSize.Bits); + } + + [Theory(DisplayName = "DataSize.FromYobiBytes should produce the expected conversion results")] + [InlineData(0, 0)] + [InlineData(1, 9.671406556917033E+24)] + [InlineData(2, 1.9342813113834067E+25)] + [InlineData(3, 2.90142196707511E+25)] + [InlineData(4, 3.8685626227668134E+25)] + [InlineData(5, 4.835703278458517E+25)] + [InlineData(6, 5.80284393415022E+25)] + [InlineData(7, 6.769984589841923E+25)] + [InlineData(8, 7.737125245533627E+25)] + [InlineData(9, 8.70426590122533E+25)] + [InlineData(10, 9.671406556917033E+25)] + public void DataSizeFromYobiBytesShouldProduceTheExpectedConversionResults(double yobiBytes, double bits) + { + // Arrange / Act + DataSize dataSize = DataSize.FromYobiBytes(yobiBytes); + + // Assert + Assert.Equal(yobiBytes, dataSize.YobiBytes); + Assert.Equal(bits, dataSize.Bits); + } +} diff --git a/OnixLabs.Core/Numerics/GenericMath.cs b/OnixLabs.Core/Numerics/GenericMath.cs new file mode 100644 index 0000000..c9f5e1d --- /dev/null +++ b/OnixLabs.Core/Numerics/GenericMath.cs @@ -0,0 +1,43 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.Numerics; + +/// +/// Provides generic mathematical functions. +/// +internal static class GenericMath +{ + /// + /// Calculates the power of the specified value, raised by the specified exponent. + /// + /// The value to raise to the power of the specified exponent. + /// The specified exponent to raise the value by. + /// The underlying type. + /// Returns the power of the specified value, raised by the specified exponent. + public static T Pow(T value, int exponent) where T : INumber + { + if (exponent == 0) return T.One; + if (exponent == 1 || value == T.One) return value; + + T result = value; + int count = int.Abs(exponent); + + while (--count > 0) result *= value; + + return exponent > 1 ? result : T.One / result; + } +} diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj index 199dc2b..d838b8b 100644 --- a/OnixLabs.Core/OnixLabs.Core.csproj +++ b/OnixLabs.Core/OnixLabs.Core.csproj @@ -51,4 +51,5 @@ + diff --git a/OnixLabs.Core/Units/DataSize.Arithmetic.cs b/OnixLabs.Core/Units/DataSize.Arithmetic.cs new file mode 100644 index 0000000..099b604 --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.Arithmetic.cs @@ -0,0 +1,106 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Core.Units; + +public readonly partial struct DataSize +{ + /// + /// Computes the sum of the specified values. + /// + /// The left-hand value to add to. + /// The right-hand value to add. + /// Returns the sum of the specified values. + public static DataSize Add(DataSize left, DataSize right) + { + return new DataSize(left.Bits + right.Bits); + } + + /// + /// Computes the difference between the specified values. + /// + /// The left-hand value to subtract from. + /// The right-hand value to subtract. + /// Returns the difference between the specified values. + public static DataSize Subtract(DataSize left, DataSize right) + { + return new DataSize(left.Bits - right.Bits); + } + + /// + /// Computes the product of the specified values. + /// + /// The left-hand value to multiply. + /// The right-hand value to multiply by. + /// Returns the product of the specified values. + public static DataSize Multiply(DataSize left, DataSize right) + { + return new DataSize(left.Bits * right.Bits); + } + + /// + /// Computes the quotient of the specified values. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// Returns the quotient of the specified values. + public static DataSize Divide(DataSize left, DataSize right) + { + return new DataSize(left.Bits / right.Bits); + } + + /// + /// Computes the sum of the specified values. + /// + /// The left-hand value to add to. + /// The right-hand value to add. + /// Returns the sum of the specified values. + public static DataSize operator +(DataSize left, DataSize right) + { + return Add(left, right); + } + + /// + /// Computes the difference between the specified values. + /// + /// The left-hand value to subtract from. + /// The right-hand value to subtract. + /// Returns the difference between the specified values. + public static DataSize operator -(DataSize left, DataSize right) + { + return Subtract(left, right); + } + + /// + /// Computes the product of the specified values. + /// + /// The left-hand value to multiply. + /// The right-hand value to multiply by. + /// Returns the product of the specified values. + public static DataSize operator *(DataSize left, DataSize right) + { + return Multiply(left, right); + } + + /// + /// Computes the quotient of the specified values. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// Returns the quotient of the specified values. + public static DataSize operator /(DataSize left, DataSize right) + { + return Divide(left, right); + } +} diff --git a/OnixLabs.Core/Units/DataSize.Comparable.cs b/OnixLabs.Core/Units/DataSize.Comparable.cs new file mode 100644 index 0000000..1a994e3 --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.Comparable.cs @@ -0,0 +1,100 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Units; + +public readonly partial struct DataSize : IComparable>, IComparable +{ + /// + /// Compares two values and returns an integer that indicates + /// whether the left-hand value is less than, equal to, or greater than the right-hand value. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns a value that indicates the relative order of the objects being compared. + public static int Compare(DataSize left, DataSize right) + { + return left.Bits.CompareTo(right.Bits); + } + + /// + /// Compares the current instance with another object of the same type and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other object. + /// + /// An object to compare with this instance. + /// Returns a value that indicates the relative order of the objects being compared. + public int CompareTo(DataSize other) + { + return Compare(this, other); + } + + /// + /// Compares the current instance with another object of the same type and returns an integer that indicates + /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the + /// other object. + /// + /// An object to compare with this instance. + /// Returns a value that indicates the relative order of the objects being compared. + public int CompareTo(object? obj) + { + return this.CompareObject(obj); + } + + /// + /// Performs a greater than comparison check between two values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the left-hand operand is greater than right-hand operand; otherwise, false. + public static bool operator >(DataSize left, DataSize right) + { + return Compare(left, right) is 1; + } + + /// + /// Performs a greater than or equal comparison check between two values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the left-hand operand is greater than or equal to right-hand operand; otherwise, false. + public static bool operator >=(DataSize left, DataSize right) + { + return Compare(left, right) is 1 or 0; + } + + /// + /// Performs a less than comparison check between two values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the left-hand operand is less than right-hand operand; otherwise, false. + public static bool operator <(DataSize left, DataSize right) + { + return Compare(left, right) is -1; + } + + /// + /// Performs a less than or equal comparison check between two values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the left-hand operand is less than or equal to right-hand operand; otherwise, false. + public static bool operator <=(DataSize left, DataSize right) + { + return Compare(left, right) is -1 or 0; + } +} diff --git a/OnixLabs.Core/Units/DataSize.Constants.cs b/OnixLabs.Core/Units/DataSize.Constants.cs new file mode 100644 index 0000000..cb14099 --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.Constants.cs @@ -0,0 +1,63 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Core.Units; + +public readonly partial struct DataSize +{ + /// + /// Represents a zero-bit value. + /// + public static DataSize Zero => default; + + /// + /// Gets the number of bits per nibble. + /// + private static T BitsPerNibble => T.CreateChecked(4); + + /// + /// Gets the number of bits per byte. + /// + private static T BitsPerByte => T.CreateChecked(8); + + /// + /// Gets the number of bits per word. + /// + private static T BitsPerWord => T.CreateChecked(16); + + /// + /// Gets the number of bits per double-word. + /// + private static T BitsPerDoubleWord => T.CreateChecked(32); + + /// + /// Gets the number of bits per quad-word. + /// + private static T BitsPerQuadWord => T.CreateChecked(64); + + /// + /// Gets the value of a binary thousand. + /// + private static T BinaryThousand => T.CreateChecked(1024); + + /// + /// Gets the value of a decimal thousand. + /// + private static T DecimalThousand => T.CreateChecked(1000); + + /// + /// Gets the default format. + /// + private const string DefaultFormat = "b"; +} diff --git a/OnixLabs.Core/Units/DataSize.Equatable.cs b/OnixLabs.Core/Units/DataSize.Equatable.cs new file mode 100644 index 0000000..d220bba --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.Equatable.cs @@ -0,0 +1,82 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Units; + +public readonly partial struct DataSize : IEquatable> +{ + /// + /// Compares two instances of to determine whether their values are equal. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool Equals(DataSize left, DataSize right) + { + return left.Bits == right.Bits; + } + + /// + /// Indicates whether the current object is equal to another object of the same type. + /// + /// An object to compare with this object. + /// Returns true if the current object is equal to the other parameter; otherwise, false. + public bool Equals(DataSize other) + { + return Equals(this, other); + } + + /// + /// Checks for equality between this instance and another object. + /// + /// The object to check for equality. + /// true if the object is equal to this instance; otherwise, false. + public override bool Equals(object? obj) + { + return obj is DataSize other && Equals(other); + } + + /// + /// Serves as a hash code function for this instance. + /// + /// A hash code for this instance. + public override int GetHashCode() + { + return HashCode.Combine(Bits); + } + + /// + /// Performs an equality check between two object instances. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// True if the instances are equal; otherwise, false. + public static bool operator ==(DataSize left, DataSize right) + { + return Equals(left, right); + } + + /// + /// Performs an inequality check between two object instances. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// True if the instances are not equal; otherwise, false. + public static bool operator !=(DataSize left, DataSize right) + { + return !Equals(left, right); + } +} diff --git a/OnixLabs.Core/Units/DataSize.From.cs b/OnixLabs.Core/Units/DataSize.From.cs new file mode 100644 index 0000000..f073afc --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.From.cs @@ -0,0 +1,424 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Core.Numerics; + +namespace OnixLabs.Core.Units; + +public readonly partial struct DataSize +{ + /// + /// Creates a new instance from the specified bit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified bit value. + public static DataSize FromBits(T value) + { + return new DataSize(value); + } + + /// + /// Creates a new instance from the specified nibble value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified nibble value. + public static DataSize FromNibbles(T value) + { + return FromBits(value * BitsPerNibble); + } + + /// + /// Creates a new instance from the specified byte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified byte value. + public static DataSize FromBytes(T value) + { + return FromBits(value * BitsPerByte); + } + + /// + /// Creates a new instance from the specified word value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified word value. + public static DataSize FromWords(T value) + { + return FromBits(value * BitsPerWord); + } + + /// + /// Creates a new instance from the specified double-word value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified double-word value. + public static DataSize FromDoubleWords(T value) + { + return FromBits(value * BitsPerDoubleWord); + } + + /// + /// Creates a new instance from the specified quad-word value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified quad-word value. + public static DataSize FromQuadWords(T value) + { + return FromBits(value * BitsPerQuadWord); + } + + /// + /// Creates a new instance from the specified kilobit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified kilobit value. + public static DataSize FromKiloBits(T value) + { + return GetUnscaledBits(value, DecimalThousand, 1); + } + + /// + /// Creates a new instance from the specified kibibit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified kibibit value. + public static DataSize FromKibiBits(T value) + { + return GetUnscaledBits(value, BinaryThousand, 1); + } + + /// + /// Creates a new instance from the specified kilobyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified kilobyte value. + public static DataSize FromKiloBytes(T value) + { + return GetUnscaledBytes(value, DecimalThousand, 1); + } + + /// + /// Creates a new instance from the specified kibibyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified kibibyte value. + public static DataSize FromKibiBytes(T value) + { + return GetUnscaledBytes(value, BinaryThousand, 1); + } + + /// + /// Creates a new instance from the specified megabit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified megabit value. + public static DataSize FromMegaBits(T value) + { + return GetUnscaledBits(value, DecimalThousand, 2); + } + + /// + /// Creates a new instance from the specified mebibit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified mebibit value. + public static DataSize FromMebiBits(T value) + { + return GetUnscaledBits(value, BinaryThousand, 2); + } + + /// + /// Creates a new instance from the specified megabyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified megabyte value. + public static DataSize FromMegaBytes(T value) + { + return GetUnscaledBytes(value, DecimalThousand, 2); + } + + /// + /// Creates a new instance from the specified mebibyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified mebibyte value. + public static DataSize FromMebiBytes(T value) + { + return GetUnscaledBytes(value, BinaryThousand, 2); + } + + /// + /// Creates a new instance from the specified gigabit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified gigabit value. + public static DataSize FromGigaBits(T value) + { + return GetUnscaledBits(value, DecimalThousand, 3); + } + + /// + /// Creates a new instance from the specified gibibit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified gibibit value. + public static DataSize FromGibiBits(T value) + { + return GetUnscaledBits(value, BinaryThousand, 3); + } + + /// + /// Creates a new instance from the specified gigabyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified gigabyte value. + public static DataSize FromGigaBytes(T value) + { + return GetUnscaledBytes(value, DecimalThousand, 3); + } + + /// + /// Creates a new instance from the specified gibibyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified gibibyte value. + public static DataSize FromGibiBytes(T value) + { + return GetUnscaledBytes(value, BinaryThousand, 3); + } + + /// + /// Creates a new instance from the specified terabit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified terabit value. + public static DataSize FromTeraBits(T value) + { + return GetUnscaledBits(value, DecimalThousand, 4); + } + + /// + /// Creates a new instance from the specified tebibit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified tebibit value. + public static DataSize FromTebiBits(T value) + { + return GetUnscaledBits(value, BinaryThousand, 4); + } + + /// + /// Creates a new instance from the specified terabyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified terabyte value. + public static DataSize FromTeraBytes(T value) + { + return GetUnscaledBytes(value, DecimalThousand, 4); + } + + /// + /// Creates a new instance from the specified tebibyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified tebibyte value. + public static DataSize FromTebiBytes(T value) + { + return GetUnscaledBytes(value, BinaryThousand, 4); + } + + /// + /// Creates a new instance from the specified petabit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified petabit value. + public static DataSize FromPetaBits(T value) + { + return GetUnscaledBits(value, DecimalThousand, 5); + } + + /// + /// Creates a new instance from the specified pebibit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified pebibit value. + public static DataSize FromPebiBits(T value) + { + return GetUnscaledBits(value, BinaryThousand, 5); + } + + /// + /// Creates a new instance from the specified petabyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified petabyte value. + public static DataSize FromPetaBytes(T value) + { + return GetUnscaledBytes(value, DecimalThousand, 5); + } + + /// + /// Creates a new instance from the specified pebibyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified pebibyte value. + public static DataSize FromPebiBytes(T value) + { + return GetUnscaledBytes(value, BinaryThousand, 5); + } + + /// + /// Creates a new instance from the specified exabit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified exabit value. + public static DataSize FromExaBits(T value) + { + return GetUnscaledBits(value, DecimalThousand, 6); + } + + /// + /// Creates a new instance from the specified exbibit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified exbibit value. + public static DataSize FromExbiBits(T value) + { + return GetUnscaledBits(value, BinaryThousand, 6); + } + + /// + /// Creates a new instance from the specified exabyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified exabyte value. + public static DataSize FromExaBytes(T value) + { + return GetUnscaledBytes(value, DecimalThousand, 6); + } + + /// + /// Creates a new instance from the specified exbibyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified exbibyte value. + public static DataSize FromExbiBytes(T value) + { + return GetUnscaledBytes(value, BinaryThousand, 6); + } + + /// + /// Creates a new instance from the specified zettabit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified zettabit value. + public static DataSize FromZettaBits(T value) + { + return GetUnscaledBits(value, DecimalThousand, 7); + } + + /// + /// Creates a new instance from the specified zebibit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified zebibit value. + public static DataSize FromZebiBits(T value) + { + return GetUnscaledBits(value, BinaryThousand, 7); + } + + /// + /// Creates a new instance from the specified zettabyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified zettabyte value. + public static DataSize FromZettaBytes(T value) + { + return GetUnscaledBytes(value, DecimalThousand, 7); + } + + /// + /// Creates a new instance from the specified zebibyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified zebibyte value. + public static DataSize FromZebiBytes(T value) + { + return GetUnscaledBytes(value, BinaryThousand, 7); + } + + /// + /// Creates a new instance from the specified yottabit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified yottabit value. + public static DataSize FromYottaBits(T value) + { + return GetUnscaledBits(value, DecimalThousand, 8); + } + + /// + /// Creates a new instance from the specified yobibit value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified yobibit value. + public static DataSize FromYobiBits(T value) + { + return GetUnscaledBits(value, BinaryThousand, 8); + } + + /// + /// Creates a new instance from the specified yottabyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified yottabyte value. + public static DataSize FromYottaBytes(T value) + { + return GetUnscaledBytes(value, DecimalThousand, 8); + } + + /// + /// Creates a new instance from the specified yobibyte value. + /// + /// The value from which to create a new instance. + /// Returns a new instance from the specified yobibyte value. + public static DataSize FromYobiBytes(T value) + { + return GetUnscaledBytes(value, BinaryThousand, 8); + } + + /// + /// Gets the number of bits in the specified value. + /// + /// The value from which to calculate the number of bits. + /// A value equalling either or to raise. + /// The exponent to raise the thousand value by. + /// Returns the number of bits in the specified value. + private static DataSize GetUnscaledBits(T value, T thousand, int exponent) + { + return new DataSize(value * GenericMath.Pow(thousand, exponent)); + } + + /// + /// Gets the number of bits in the specified value. + /// + /// The value from which to calculate the number of bits. + /// A value equalling either or to raise. + /// The exponent to raise the thousand value by. + /// Returns the number of bits in the specified value. + private static DataSize GetUnscaledBytes(T value, T thousand, int exponent) + { + return new DataSize(value * (GenericMath.Pow(thousand, exponent) * BitsPerByte)); + } +} diff --git a/OnixLabs.Core/Units/DataSize.Static.Arithmetic.cs b/OnixLabs.Core/Units/DataSize.Static.Arithmetic.cs new file mode 100644 index 0000000..ed569e5 --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.Static.Arithmetic.cs @@ -0,0 +1,71 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.Units; + +/// +/// Provides functionality for managing instances. +/// +public static partial class DataSize +{ + /// + /// Computes the sum of the specified values. + /// + /// The left-hand value to add to. + /// The right-hand value to add. + /// The underlying type that represents the unit. + /// Returns the sum of the specified values. + public static DataSize Add(DataSize left, DataSize right) where T : IFloatingPoint + { + return DataSize.Add(left, right); + } + + /// + /// Computes the difference between the specified values. + /// + /// The left-hand value to subtract from. + /// The right-hand value to subtract. + /// The underlying type that represents the unit. + /// Returns the difference between the specified values. + public static DataSize Subtract(DataSize left, DataSize right) where T : IFloatingPoint + { + return DataSize.Subtract(left, right); + } + + /// + /// Computes the product of the specified values. + /// + /// The left-hand value to multiply. + /// The right-hand value to multiply by. + /// The underlying type that represents the unit. + /// Returns the product of the specified values. + public static DataSize Multiply(DataSize left, DataSize right) where T : IFloatingPoint + { + return DataSize.Multiply(left, right); + } + + /// + /// Computes the quotient of the specified values. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// The underlying type that represents the unit. + /// Returns the quotient of the specified values. + public static DataSize Divide(DataSize left, DataSize right) where T : IFloatingPoint + { + return DataSize.Divide(left, right); + } +} diff --git a/OnixLabs.Core/Units/DataSize.Static.Comparison.cs b/OnixLabs.Core/Units/DataSize.Static.Comparison.cs new file mode 100644 index 0000000..b6adc6b --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.Static.Comparison.cs @@ -0,0 +1,45 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.Units; + +public static partial class DataSize +{ + /// + /// Compares two values and returns an integer that indicates + /// whether the left-hand value is less than, equal to, or greater than the right-hand value. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// The underlying type that represents the unit. + /// Returns a value that indicates the relative order of the objects being compared. + public static int Compare(DataSize left, DataSize right) where T : IFloatingPoint + { + return DataSize.Compare(left, right); + } + + /// + /// Compares two instances of to determine whether their values are equal. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// The underlying type that represents the unit. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool Equals(DataSize left, DataSize right) where T : IFloatingPoint + { + return DataSize.Equals(left, right); + } +} diff --git a/OnixLabs.Core/Units/DataSize.Static.From.cs b/OnixLabs.Core/Units/DataSize.Static.From.cs new file mode 100644 index 0000000..40a2c46 --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.Static.From.cs @@ -0,0 +1,438 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.Units; + +public static partial class DataSize +{ + /// + /// Creates a new instance from the specified bit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified bit value. + public static DataSize FromBits(T value) where T : IFloatingPoint + { + return DataSize.FromBits(value); + } + + /// + /// Creates a new instance from the specified nibble value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified nibble value. + public static DataSize FromNibbles(T value) where T : IFloatingPoint + { + return DataSize.FromNibbles(value); + } + + /// + /// Creates a new instance from the specified byte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified byte value. + public static DataSize FromBytes(T value) where T : IFloatingPoint + { + return DataSize.FromBytes(value); + } + + /// + /// Creates a new instance from the specified word value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified word value. + public static DataSize FromWords(T value) where T : IFloatingPoint + { + return DataSize.FromWords(value); + } + + /// + /// Creates a new instance from the specified double-word value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified double-word value. + public static DataSize FromDoubleWords(T value) where T : IFloatingPoint + { + return DataSize.FromDoubleWords(value); + } + + /// + /// Creates a new instance from the specified quad-word value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified quad-word value. + public static DataSize FromQuadWords(T value) where T : IFloatingPoint + { + return DataSize.FromQuadWords(value); + } + + /// + /// Creates a new instance from the specified kilobit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified kilobit value. + public static DataSize FromKiloBits(T value) where T : IFloatingPoint + { + return DataSize.FromKiloBits(value); + } + + /// + /// Creates a new instance from the specified kibibit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified kibibit value. + public static DataSize FromKibiBits(T value) where T : IFloatingPoint + { + return DataSize.FromKibiBits(value); + } + + /// + /// Creates a new instance from the specified kilobyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified kilobyte value. + public static DataSize FromKiloBytes(T value) where T : IFloatingPoint + { + return DataSize.FromKiloBytes(value); + } + + /// + /// Creates a new instance from the specified kibibyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified kibibyte value. + public static DataSize FromKibiBytes(T value) where T : IFloatingPoint + { + return DataSize.FromKibiBytes(value); + } + + /// + /// Creates a new instance from the specified megabit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified megabit value. + public static DataSize FromMegaBits(T value) where T : IFloatingPoint + { + return DataSize.FromMegaBits(value); + } + + /// + /// Creates a new instance from the specified mebibit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified mebibit value. + public static DataSize FromMebiBits(T value) where T : IFloatingPoint + { + return DataSize.FromMebiBits(value); + } + + /// + /// Creates a new instance from the specified megabyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified megabyte value. + public static DataSize FromMegaBytes(T value) where T : IFloatingPoint + { + return DataSize.FromMegaBytes(value); + } + + /// + /// Creates a new instance from the specified mebibyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified mebibyte value. + public static DataSize FromMebiBytes(T value) where T : IFloatingPoint + { + return DataSize.FromMebiBytes(value); + } + + /// + /// Creates a new instance from the specified gigabit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified gigabit value. + public static DataSize FromGigaBits(T value) where T : IFloatingPoint + { + return DataSize.FromGigaBits(value); + } + + /// + /// Creates a new instance from the specified gibibit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified gibibit value. + public static DataSize FromGibiBits(T value) where T : IFloatingPoint + { + return DataSize.FromGibiBits(value); + } + + /// + /// Creates a new instance from the specified gigabyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified gigabyte value. + public static DataSize FromGigaBytes(T value) where T : IFloatingPoint + { + return DataSize.FromGigaBytes(value); + } + + /// + /// Creates a new instance from the specified gibibyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified gibibyte value. + public static DataSize FromGibiBytes(T value) where T : IFloatingPoint + { + return DataSize.FromGibiBytes(value); + } + + /// + /// Creates a new instance from the specified terabit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified terabit value. + public static DataSize FromTeraBits(T value) where T : IFloatingPoint + { + return DataSize.FromTeraBits(value); + } + + /// + /// Creates a new instance from the specified tebibit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified tebibit value. + public static DataSize FromTebiBits(T value) where T : IFloatingPoint + { + return DataSize.FromTebiBits(value); + } + + /// + /// Creates a new instance from the specified terabyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified terabyte value. + public static DataSize FromTeraBytes(T value) where T : IFloatingPoint + { + return DataSize.FromTeraBytes(value); + } + + /// + /// Creates a new instance from the specified tebibyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified tebibyte value. + public static DataSize FromTebiBytes(T value) where T : IFloatingPoint + { + return DataSize.FromTebiBytes(value); + } + + /// + /// Creates a new instance from the specified petabit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified petabit value. + public static DataSize FromPetaBits(T value) where T : IFloatingPoint + { + return DataSize.FromPetaBits(value); + } + + /// + /// Creates a new instance from the specified pebibit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified pebibit value. + public static DataSize FromPebiBits(T value) where T : IFloatingPoint + { + return DataSize.FromPebiBits(value); + } + + /// + /// Creates a new instance from the specified petabyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified petabyte value. + public static DataSize FromPetaBytes(T value) where T : IFloatingPoint + { + return DataSize.FromPetaBytes(value); + } + + /// + /// Creates a new instance from the specified pebibyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified pebibyte value. + public static DataSize FromPebiBytes(T value) where T : IFloatingPoint + { + return DataSize.FromPebiBytes(value); + } + + /// + /// Creates a new instance from the specified exabit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified exabit value. + public static DataSize FromExaBits(T value) where T : IFloatingPoint + { + return DataSize.FromExaBits(value); + } + + /// + /// Creates a new instance from the specified exbibit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified exbibit value. + public static DataSize FromExbiBits(T value) where T : IFloatingPoint + { + return DataSize.FromExbiBits(value); + } + + /// + /// Creates a new instance from the specified exabyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified exabyte value. + public static DataSize FromExaBytes(T value) where T : IFloatingPoint + { + return DataSize.FromExaBytes(value); + } + + /// + /// Creates a new instance from the specified exbibyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified exbibyte value. + public static DataSize FromExbiBytes(T value) where T : IFloatingPoint + { + return DataSize.FromExbiBytes(value); + } + + /// + /// Creates a new instance from the specified zettabit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified zettabit value. + public static DataSize FromZettaBits(T value) where T : IFloatingPoint + { + return DataSize.FromZettaBits(value); + } + + /// + /// Creates a new instance from the specified zebibit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified zebibit value. + public static DataSize FromZebiBits(T value) where T : IFloatingPoint + { + return DataSize.FromZebiBits(value); + } + + /// + /// Creates a new instance from the specified zettabyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified zettabyte value. + public static DataSize FromZettaBytes(T value) where T : IFloatingPoint + { + return DataSize.FromZettaBytes(value); + } + + /// + /// Creates a new instance from the specified zebibyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified zebibyte value. + public static DataSize FromZebiBytes(T value) where T : IFloatingPoint + { + return DataSize.FromZebiBytes(value); + } + + /// + /// Creates a new instance from the specified yottabit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified yottabit value. + public static DataSize FromYottaBits(T value) where T : IFloatingPoint + { + return DataSize.FromYottaBits(value); + } + + /// + /// Creates a new instance from the specified yobibit value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified yobibit value. + public static DataSize FromYobiBits(T value) where T : IFloatingPoint + { + return DataSize.FromYobiBits(value); + } + + /// + /// Creates a new instance from the specified yottabyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified yottabyte value. + public static DataSize FromYottaBytes(T value) where T : IFloatingPoint + { + return DataSize.FromYottaBytes(value); + } + + /// + /// Creates a new instance from the specified yobibyte value. + /// + /// The value from which to create a new instance. + /// The underlying type that represents the unit. + /// Returns a new instance from the specified yobibyte value. + public static DataSize FromYobiBytes(T value) where T : IFloatingPoint + { + return DataSize.FromYobiBytes(value); + } +} diff --git a/OnixLabs.Core/Units/DataSize.To.cs b/OnixLabs.Core/Units/DataSize.To.cs new file mode 100644 index 0000000..f831da8 --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.To.cs @@ -0,0 +1,185 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; + +namespace OnixLabs.Core.Units; + +public readonly partial struct DataSize : IFormattable +{ + /// + /// Formats the value of the current instance using the specified format. + /// Valid formats for include: + /// + /// FormatDescription + /// bBits + /// nNibbles + /// BBytes + /// WWords + /// DWDoubleWords + /// QWQuadWords + /// KbKiloBits + /// KibKibiBits + /// KBKiloBytes + /// KiBKibiBytes + /// MbMegaBits + /// MibMebiBits + /// MBMegaBytes + /// MiBMebiBytes + /// GbGigaBits + /// GibGibiBits + /// GBGigaBytes + /// GiBGibiBytes + /// TbTeraBits + /// TibTebiBits + /// TBTeraBytes + /// TiBTebiBytes + /// PbPetaBits + /// PibPebiBits + /// PBPetaBytes + /// PiBPebiBytes + /// EbExaBits + /// EibExbiBits + /// EBExaBytes + /// EiBExbiBytes + /// ZbZettaBits + /// ZibZebiBits + /// ZBZettaBytes + /// ZiBZebiBytes + /// YbYottaBits + /// YibYobiBits + /// YBYottaBytes + /// YiBYobiBytes + /// + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// Returns the value of the current instance in the specified format. + /// If the specified format is invalid. + public string ToString(string? format, IFormatProvider? formatProvider) + { + string formatOrDefault = format ?? DefaultFormat; + IFormatProvider formatProviderOrDefault = formatProvider ?? CultureInfo.CurrentCulture; + + T value = formatOrDefault switch + { + "b" => Bits, + "n" => Nibbles, + "B" => Bytes, + "W" => Words, + "DW" => DoubleWords, + "QW" => QuadWords, + "Kb" => KiloBits, + "Kib" => KibiBits, + "KB" => KiloBytes, + "KiB" => KibiBytes, + "Mb" => MegaBits, + "Mib" => MebiBits, + "MB" => MegaBytes, + "MiB" => MebiBytes, + "Gb" => GigaBits, + "Gib" => GibiBits, + "GB" => GigaBytes, + "GiB" => GibiBytes, + "Tb" => TeraBits, + "Tib" => TebiBits, + "TB" => TeraBytes, + "TiB" => TebiBytes, + "Pb" => PetaBits, + "Pib" => PebiBits, + "PB" => PetaBytes, + "PiB" => PebiBytes, + "Eb" => ExaBits, + "Eib" => ExbiBits, + "EB" => ExaBytes, + "EiB" => ExbiBytes, + "Zb" => ZettaBits, + "Zib" => ZebiBits, + "ZB" => ZettaBytes, + "ZiB" => ZebiBytes, + "Yb" => YottaBits, + "Yib" => YobiBits, + "YB" => YottaBytes, + "YiB" => YobiBytes, + _ => throw new ArgumentException($"Invalid format specifier: {format}.") + }; + + return $"{value.ToString("R", formatProviderOrDefault)} {formatOrDefault}"; + } + + /// + /// Formats the value of the current instance using the specified format. + /// Valid formats for include: + /// + /// FormatDescription + /// bBits + /// nNibbles + /// BBytes + /// WWords + /// DWDoubleWords + /// QWQuadWords + /// KbKiloBits + /// KibKibiBits + /// KBKiloBytes + /// KiBKibiBytes + /// MbMegaBits + /// MibMebiBits + /// MBMegaBytes + /// MiBMebiBytes + /// GbGigaBits + /// GibGibiBits + /// GBGigaBytes + /// GiBGibiBytes + /// TbTeraBits + /// TibTebiBits + /// TBTeraBytes + /// TiBTebiBytes + /// PbPetaBits + /// PibPebiBits + /// PBPetaBytes + /// PiBPebiBytes + /// EbExaBits + /// EibExbiBits + /// EBExaBytes + /// EiBExbiBytes + /// ZbZettaBits + /// ZibZebiBits + /// ZBZettaBytes + /// ZiBZebiBytes + /// YbYottaBits + /// YibYobiBits + /// YBYottaBytes + /// YiBYobiBytes + /// + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// Returns the value of the current instance in the specified format. + /// If the specified format is invalid. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + { + return ToString(format.ToString(), formatProvider); + } + + /// + /// Formats the value of the current instance using the default format. + /// + /// Returns the value of the current instance in the specified format. + /// If the specified format is invalid. + public override string ToString() + { + return ToString(DefaultFormat); + } +} diff --git a/OnixLabs.Core/Units/DataSize.cs b/OnixLabs.Core/Units/DataSize.cs new file mode 100644 index 0000000..c7560a0 --- /dev/null +++ b/OnixLabs.Core/Units/DataSize.cs @@ -0,0 +1,247 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using OnixLabs.Core.Numerics; + +namespace OnixLabs.Core.Units; + +/// +/// Represents a unit of DataSize. +/// +/// The underlying type that represents the current unit. +public readonly partial struct DataSize where T : IFloatingPoint +{ + /// + /// Initializes a new instance of the struct. + /// + /// The initial DataSize value in Bits. + private DataSize(T bits) + { + Require(bits >= T.Zero, $"Cannot initialize {nameof(DataSize)} from negative value.", nameof(bits)); + Bits = bits; + } + + /// + /// Gets the current in bits. + /// + public T Bits { get; } + + /// + /// Gets the current in nibbles. + /// + public T Nibbles => Bits / BitsPerNibble; + + /// + /// Gets the current in bytes. + /// + public T Bytes => Bits / BitsPerByte; + + /// + /// Gets the current in words. + /// + public T Words => Bits / BitsPerWord; + + /// + /// Gets the current in double-words. + /// + public T DoubleWords => Bits / BitsPerDoubleWord; + + /// + /// Gets the current in quad-words. + /// + public T QuadWords => Bits / BitsPerQuadWord; + + /// + /// Gets the current in kilobits. + /// + public T KiloBits => GetScaledBits(DecimalThousand, 1); + + /// + /// Gets the current in kibibits. + /// + public T KibiBits => GetScaledBits(BinaryThousand, 1); + + /// + /// Gets the current in kilobytes. + /// + public T KiloBytes => GetScaledBytes(DecimalThousand, 1); + + /// + /// Gets the current in kibibytes. + /// + public T KibiBytes => GetScaledBytes(BinaryThousand, 1); + + /// + /// Gets the current in megabits. + /// + public T MegaBits => GetScaledBits(DecimalThousand, 2); + + /// + /// Gets the current in mebibits. + /// + public T MebiBits => GetScaledBits(BinaryThousand, 2); + + /// + /// Gets the current in megabytes. + /// + public T MegaBytes => GetScaledBytes(DecimalThousand, 2); + + /// + /// Gets the current in mebibytes. + /// + public T MebiBytes => GetScaledBytes(BinaryThousand, 2); + + /// + /// Gets the current in gigabits. + /// + public T GigaBits => GetScaledBits(DecimalThousand, 3); + + /// + /// Gets the current in gibibits. + /// + public T GibiBits => GetScaledBits(BinaryThousand, 3); + + /// + /// Gets the current in gigbytes. + /// + public T GigaBytes => GetScaledBytes(DecimalThousand, 3); + + /// + /// Gets the current in gibibytes. + /// + public T GibiBytes => GetScaledBytes(BinaryThousand, 3); + + /// + /// Gets the current in terabits. + /// + public T TeraBits => GetScaledBits(DecimalThousand, 4); + + /// + /// Gets the current in tebibits. + /// + public T TebiBits => GetScaledBits(BinaryThousand, 4); + + /// + /// Gets the current in terabytes. + /// + public T TeraBytes => GetScaledBytes(DecimalThousand, 4); + + /// + /// Gets the current in tebibytes. + /// + public T TebiBytes => GetScaledBytes(BinaryThousand, 4); + + /// + /// Gets the current in petabits. + /// + public T PetaBits => GetScaledBits(DecimalThousand, 5); + + /// + /// Gets the current in pebibits. + /// + public T PebiBits => GetScaledBits(BinaryThousand, 5); + + /// + /// Gets the current in petabytes. + /// + public T PetaBytes => GetScaledBytes(DecimalThousand, 5); + + /// + /// Gets the current in pebibytes. + /// + public T PebiBytes => GetScaledBytes(BinaryThousand, 5); + + /// + /// Gets the current in exabits. + /// + public T ExaBits => GetScaledBits(DecimalThousand, 6); + + /// + /// Gets the current in exbibits. + /// + public T ExbiBits => GetScaledBits(BinaryThousand, 6); + + /// + /// Gets the current in exabytes. + /// + public T ExaBytes => GetScaledBytes(DecimalThousand, 6); + + /// + /// Gets the current in exbibytes. + /// + public T ExbiBytes => GetScaledBytes(BinaryThousand, 6); + + /// + /// Gets the current in zettabits. + /// + public T ZettaBits => GetScaledBits(DecimalThousand, 7); + + /// + /// Gets the current in zebibits. + /// + public T ZebiBits => GetScaledBits(BinaryThousand, 7); + + /// + /// Gets the current in zettabytes. + /// + public T ZettaBytes => GetScaledBytes(DecimalThousand, 7); + + /// + /// Gets the current in zebibytes. + /// + public T ZebiBytes => GetScaledBytes(BinaryThousand, 7); + + /// + /// Gets the current in yottabits. + /// + public T YottaBits => GetScaledBits(DecimalThousand, 8); + + /// + /// Gets the current in yobibits. + /// + public T YobiBits => GetScaledBits(BinaryThousand, 8); + + /// + /// Gets the current in yottabytes. + /// + public T YottaBytes => GetScaledBytes(DecimalThousand, 8); + + /// + /// Gets the current in yobibytes. + /// + public T YobiBytes => GetScaledBytes(BinaryThousand, 8); + + /// + /// Calculates the current divided by the specified power. + /// + /// A value equalling either or to raise. + /// The exponent to raise the thousand value by. + /// Returns the current divided by the specified power. + private T GetScaledBits(T thousand, int exponent) + { + return Bits / GenericMath.Pow(thousand, exponent); + } + + /// + /// Calculates the current divided by the specified power. + /// + /// A value equalling either or to raise. + /// The exponent to raise the thousand value by. + /// Returns the current divided by the specified power. + private T GetScaledBytes(T thousand, int exponent) + { + return Bits / (GenericMath.Pow(thousand, exponent) * BitsPerByte); + } +} diff --git a/OnixLabs.Core/Units/Temperature.To.cs b/OnixLabs.Core/Units/Temperature.To.cs index ff73a05..3debaad 100644 --- a/OnixLabs.Core/Units/Temperature.To.cs +++ b/OnixLabs.Core/Units/Temperature.To.cs @@ -21,34 +21,60 @@ namespace OnixLabs.Core.Units; { /// /// Formats the value of the current instance using the specified format. + /// Valid formats for include: + /// + /// FormatDescription + /// KKelvin + /// CCelsius + /// DDelisle + /// FFahrenheit + /// NNewton + /// RReaumur + /// RaRankine + /// /// /// The format to use, or null to use the default format. /// The provider to use to format the value. - /// The value of the current instance in the specified format. + /// Returns the value of the current instance in the specified format. + /// If the specified format is invalid. public string ToString(string? format, IFormatProvider? formatProvider = null) { - (string formatOrDefault, T value) = (format ?? DefaultFormat).ToUpper() switch + string formatOrDefault = format ?? DefaultFormat; + IFormatProvider formatProviderOrDefault = formatProvider ?? CultureInfo.CurrentCulture; + + T value = formatOrDefault switch { - "K" => ("K", Kelvin), - "C" => ("C", Celsius), - "D" => ("D", Delisle), - "F" => ("F", Fahrenheit), - "N" => ("N", Newton), - "R" => ("R", Reaumur), - "RA" => ("Ra", Rankine), - _ => throw new ArgumentException($"Invalid format specifier: {format}") + "K" => Kelvin, + "C" => Celsius, + "D" => Delisle, + "F" => Fahrenheit, + "N" => Newton, + "R" => Reaumur, + "Ra" => Rankine, + _ => throw new ArgumentException($"Invalid format specifier: {format}.") }; - string number = value.ToString("R", formatProvider as CultureInfo ?? CultureInfo.CurrentCulture); - return $"{number}°{formatOrDefault}"; + return $"{value.ToString("R", formatProviderOrDefault)}°{formatOrDefault}"; } /// /// Formats the value of the current instance using the specified format. + /// Valid formats for include: + /// + /// FormatDescription + /// KKelvin + /// CCelsius + /// DDelisle + /// FFahrenheit + /// NNewton + /// RReaumur + /// RaRankine + /// /// /// The format to use, or null to use the default format. /// The provider to use to format the value. - /// The value of the current instance in the specified format. + /// Returns the value of the current instance in the specified format. + /// If the specified format is invalid. public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) { return ToString(format.ToString(), formatProvider); @@ -57,9 +83,10 @@ public string ToString(ReadOnlySpan format, IFormatProvider? formatProvide /// /// Formats the value of the current instance using the default format. /// - /// The value of the current instance in the default format. + /// Returns the value of the current instance in the specified format. + /// If the specified format is invalid. public override string ToString() { - return ToString(DefaultFormat, CultureInfo.CurrentCulture); + return ToString(DefaultFormat); } } diff --git a/OnixLabs.Playground/Program.cs b/OnixLabs.Playground/Program.cs index 6674ac3..ab33f8f 100644 --- a/OnixLabs.Playground/Program.cs +++ b/OnixLabs.Playground/Program.cs @@ -12,11 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; +using OnixLabs.Core.Units; + namespace OnixLabs.Playground; internal static class Program { public static void Main() { + DataSize ds = DataSize.FromBytes(1026.0); + Console.WriteLine(ds.ToString("KiB")); } } From b374c4519971b4bed902a9cb230bfd44eac67aec Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:36:19 +0000 Subject: [PATCH 07/14] Style changes to provide Preconditions and Collections as global static imports (#32) --- .../Collections/CollectionTests.cs | 72 +++++++++---------- .../Linq/IEnumerableExtensionTests.cs | 4 +- .../OnixLabs.Core.UnitTests.csproj | 21 +++--- OnixLabs.Core/OnixLabs.Core.csproj | 15 +--- OnixLabs.Core/Text/Base16.Constants.cs | 2 +- OnixLabs.Core/Text/Base32.Constants.cs | 2 +- OnixLabs.Core/Text/Base58.Constants.cs | 2 +- OnixLabs.Core/Text/Base64.Constants.cs | 2 +- .../OnixLabs.Playground.csproj | 5 +- .../HashTests.cs | 12 ++-- .../MerkleTreeGenericTests.cs | 4 +- ...abs.Security.Cryptography.UnitTests.csproj | 10 ++- .../OnixLabs.Security.Cryptography.csproj | 11 +-- 13 files changed, 71 insertions(+), 91 deletions(-) diff --git a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs index 5627a80..4b9ddf0 100644 --- a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs +++ b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs @@ -46,7 +46,7 @@ public void CollectionsEmptyEnumerableShouldProduceTheExpectedResult() { // Given IEnumerable expected = Enumerable.Empty(); - IEnumerable actual = Collection.EmptyEnumerable(); + IEnumerable actual = EmptyEnumerable(); // Then Assert.Equal(expected, actual); @@ -57,7 +57,7 @@ public void CollectionsEmptyArrayShouldProduceTheExpectedResult() { // Given object[] expected = Array.Empty(); - object[] actual = Collection.EmptyArray(); + object[] actual = EmptyArray(); // Then Assert.Equal(expected, actual); @@ -68,7 +68,7 @@ public void CollectionsEmptyImmutableArrayShouldProduceTheExpectedResult() { // Given ImmutableArray expected = ImmutableArray.Create(); - ImmutableArray actual = Collection.EmptyImmutableArray(); + ImmutableArray actual = EmptyImmutableArray(); // Then Assert.Equal(expected, actual); @@ -79,7 +79,7 @@ public void CollectionsEmptyListShouldProduceTheExpectedResult() { // Given List expected = new(); - List actual = Collection.EmptyList(); + List actual = EmptyList(); // Then Assert.Equal(expected, actual); @@ -90,7 +90,7 @@ public void CollectionsEmptyImmutableListShouldProduceTheExpectedResult() { // Given ImmutableList expected = ImmutableList.Create(); - ImmutableList actual = Collection.EmptyImmutableList(); + ImmutableList actual = EmptyImmutableList(); // Then Assert.Equal(expected, actual); @@ -101,7 +101,7 @@ public void CollectionsEmptyDictionaryShouldProduceTheExpectedResult() { // Given Dictionary expected = new(); - Dictionary actual = Collection.EmptyDictionary(); + Dictionary actual = EmptyDictionary(); // Then Assert.Equal(expected, actual); @@ -112,7 +112,7 @@ public void CollectionsEmptyImmutableDictionaryShouldProduceTheExpectedResult() { // Given ImmutableDictionary expected = ImmutableDictionary.Create(); - ImmutableDictionary actual = Collection.EmptyImmutableDictionary(); + ImmutableDictionary actual = EmptyImmutableDictionary(); // Then Assert.Equal(expected, actual); @@ -123,7 +123,7 @@ public void CollectionsEmptySortedDictionaryShouldProduceTheExpectedResult() { // Given SortedDictionary expected = new(); - SortedDictionary actual = Collection.EmptySortedDictionary(); + SortedDictionary actual = EmptySortedDictionary(); // Then Assert.Equal(expected, actual); @@ -134,7 +134,7 @@ public void CollectionsEmptyImmutableSortedDictionaryShouldProduceTheExpectedRes { // Given ImmutableSortedDictionary expected = ImmutableSortedDictionary.Create(); - ImmutableSortedDictionary actual = Collection.EmptyImmutableSortedDictionary(); + ImmutableSortedDictionary actual = EmptyImmutableSortedDictionary(); // Then Assert.Equal(expected, actual); @@ -145,7 +145,7 @@ public void CollectionsEmptyHashSetShouldProduceTheExpectedResult() { // Given HashSet expected = new(); - HashSet actual = Collection.EmptyHashSet(); + HashSet actual = EmptyHashSet(); // Then Assert.Equal(expected, actual); @@ -156,7 +156,7 @@ public void CollectionsEmptyImmutableHashSetShouldProduceTheExpectedResult() { // Given ImmutableHashSet expected = ImmutableHashSet.Create(); - ImmutableHashSet actual = Collection.EmptyImmutableHashSet(); + ImmutableHashSet actual = EmptyImmutableHashSet(); // Then Assert.Equal(expected, actual); @@ -167,7 +167,7 @@ public void CollectionsEmptySortedSetShouldProduceTheExpectedResult() { // Given SortedSet expected = new(); - SortedSet actual = Collection.EmptySortedSet(); + SortedSet actual = EmptySortedSet(); // Then Assert.Equal(expected, actual); @@ -178,7 +178,7 @@ public void CollectionsEmptyImmutableSortedSetShouldProduceTheExpectedResult() { // Given ImmutableSortedSet expected = ImmutableSortedSet.Create(); - ImmutableSortedSet actual = Collection.EmptyImmutableSortedSet(); + ImmutableSortedSet actual = EmptyImmutableSortedSet(); // Then Assert.Equal(expected, actual); @@ -189,7 +189,7 @@ public void CollectionsEmptyStackShouldProduceTheExpectedResult() { // Given Stack expected = new(); - Stack actual = Collection.EmptyStack(); + Stack actual = EmptyStack(); // Then Assert.Equal(expected, actual); @@ -200,7 +200,7 @@ public void CollectionsEmptyImmutableStackShouldProduceTheExpectedResult() { // Given ImmutableStack expected = ImmutableStack.Create(); - ImmutableStack actual = Collection.EmptyImmutableStack(); + ImmutableStack actual = EmptyImmutableStack(); // Then Assert.Equal(expected, actual); @@ -211,7 +211,7 @@ public void CollectionsEmptyQueueShouldProduceTheExpectedResult() { // Given Queue expected = new(); - Queue actual = Collection.EmptyQueue(); + Queue actual = EmptyQueue(); // Then Assert.Equal(expected, actual); @@ -222,7 +222,7 @@ public void CollectionsEmptyImmutableQueueShouldProduceTheExpectedResult() { // Given ImmutableQueue expected = ImmutableQueue.Create(); - ImmutableQueue actual = Collection.EmptyImmutableQueue(); + ImmutableQueue actual = EmptyImmutableQueue(); // Then Assert.Equal(expected, actual); @@ -233,7 +233,7 @@ public void CollectionsEnumerableOfShouldReturnTheExpectedResult() { // Given IEnumerable expected = EnumerableInitializers; - IEnumerable actual = Collection.EnumerableOf(EnumerableInitializers); + IEnumerable actual = EnumerableOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -244,7 +244,7 @@ public void CollectionsArrayOfShouldReturnTheExpectedResult() { // Given object[] expected = EnumerableInitializers.ToArray(); - object[] actual = Collection.ArrayOf(EnumerableInitializers); + object[] actual = ArrayOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -255,7 +255,7 @@ public void CollectionsImmutableArrayOfShouldReturnTheExpectedResult() { // Given ImmutableArray expected = ImmutableArray.Create(EnumerableInitializers); - ImmutableArray actual = Collection.ImmutableArrayOf(EnumerableInitializers); + ImmutableArray actual = ImmutableArrayOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -266,7 +266,7 @@ public void CollectionsListOfShouldReturnTheExpectedResult() { // Given List expected = new(EnumerableInitializers); - List actual = Collection.ListOf(EnumerableInitializers); + List actual = ListOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -277,7 +277,7 @@ public void CollectionsImmutableListOfShouldReturnTheExpectedResult() { // Given ImmutableList expected = ImmutableList.Create(EnumerableInitializers); - ImmutableList actual = Collection.ImmutableListOf(EnumerableInitializers); + ImmutableList actual = ImmutableListOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -288,7 +288,7 @@ public void CollectionsDictionaryOfShouldReturnTheExpectedResult() { // Given Dictionary expected = new(DictionaryInitializers); - Dictionary actual = Collection.DictionaryOf(DictionaryInitializers); + Dictionary actual = DictionaryOf(DictionaryInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -299,7 +299,7 @@ public void CollectionsImmutableDictionaryOfShouldReturnTheExpectedResult() { // Given ImmutableDictionary expected = new Dictionary(DictionaryInitializers).ToImmutableDictionary(); - ImmutableDictionary actual = Collection.ImmutableDictionaryOf(DictionaryInitializers); + ImmutableDictionary actual = ImmutableDictionaryOf(DictionaryInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -309,8 +309,8 @@ public void CollectionsImmutableDictionaryOfShouldReturnTheExpectedResult() public void CollectionsSortedDictionaryOfShouldReturnTheExpectedResult() { // Given - SortedDictionary expected = new(Collection.DictionaryOf(SortedDictionaryInitializers)); - SortedDictionary actual = Collection.SortedDictionaryOf(SortedDictionaryInitializers); + SortedDictionary expected = new(DictionaryOf(SortedDictionaryInitializers)); + SortedDictionary actual = SortedDictionaryOf(SortedDictionaryInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -320,9 +320,9 @@ public void CollectionsSortedDictionaryOfShouldReturnTheExpectedResult() public void CollectionsImmutableSortedDictionaryOfShouldReturnTheExpectedResult() { // Given - SortedDictionary sorted = new(Collection.DictionaryOf(SortedDictionaryInitializers)); + SortedDictionary sorted = new(DictionaryOf(SortedDictionaryInitializers)); ImmutableSortedDictionary expected = sorted.ToImmutableSortedDictionary(); - ImmutableSortedDictionary actual = Collection.ImmutableSortedDictionaryOf(SortedDictionaryInitializers); + ImmutableSortedDictionary actual = ImmutableSortedDictionaryOf(SortedDictionaryInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -333,7 +333,7 @@ public void CollectionsHashSetOfShouldReturnTheExpectedResult() { // Given HashSet expected = new(EnumerableInitializers); - HashSet actual = Collection.HashSetOf(EnumerableInitializers); + HashSet actual = HashSetOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -344,7 +344,7 @@ public void CollectionsImmutableHashSetOfShouldReturnTheExpectedResult() { // Given ImmutableHashSet expected = ImmutableHashSet.Create(EnumerableInitializers); - ImmutableHashSet actual = Collection.ImmutableHashSetOf(EnumerableInitializers); + ImmutableHashSet actual = ImmutableHashSetOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -355,7 +355,7 @@ public void CollectionsSortedSetOfShouldReturnTheExpectedResult() { // Given SortedSet expected = new(NumericInitializers); - SortedSet actual = Collection.SortedSetOf(NumericInitializers); + SortedSet actual = SortedSetOf(NumericInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -366,7 +366,7 @@ public void CollectionsImmutableSortedSetOfShouldReturnTheExpectedResult() { // Given ImmutableSortedSet expected = ImmutableSortedSet.Create(NumericInitializers); - ImmutableSortedSet actual = Collection.ImmutableSortedSetOf(NumericInitializers); + ImmutableSortedSet actual = ImmutableSortedSetOf(NumericInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -377,7 +377,7 @@ public void CollectionsStackOfShouldReturnTheExpectedResult() { // Given Stack expected = new(EnumerableInitializers); - Stack actual = Collection.StackOf(EnumerableInitializers); + Stack actual = StackOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -388,7 +388,7 @@ public void CollectionsImmutableStackOfShouldReturnTheExpectedResult() { // Given ImmutableStack expected = ImmutableStack.Create(EnumerableInitializers); - ImmutableStack actual = Collection.ImmutableStackOf(EnumerableInitializers); + ImmutableStack actual = ImmutableStackOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -399,7 +399,7 @@ public void CollectionsQueueOfShouldReturnTheExpectedResult() { // Given Queue expected = new(EnumerableInitializers); - Queue actual = Collection.QueueOf(EnumerableInitializers); + Queue actual = QueueOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); @@ -410,7 +410,7 @@ public void CollectionsImmutableQueueOfShouldReturnTheExpectedResult() { // Given ImmutableQueue expected = ImmutableQueue.Create(EnumerableInitializers); - ImmutableQueue actual = Collection.ImmutableQueueOf(EnumerableInitializers); + ImmutableQueue actual = ImmutableQueueOf(EnumerableInitializers); // Then Assert.True(expected.SequenceEqual(actual)); diff --git a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs index e23f23a..863697b 100644 --- a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs @@ -372,7 +372,7 @@ public void NoneShouldProduceExpectedResultFalseAll() public void SumShouldProduceExpectedResult() { // Given - IEnumerable elements = Collection.ListOf(12.34m, 34.56m, 56.78m); + IEnumerable elements = ListOf(12.34m, 34.56m, 56.78m); decimal expected = 103.68m; // When @@ -389,7 +389,7 @@ public void SumWithSelectorShouldProduceExpectedResult() Numeric element1 = new(1234.567m); Numeric element2 = new(890.1234m); Numeric element3 = new(56.78901m); - IEnumerable> elements = Collection.ListOf(element1, element2, element3); + IEnumerable> elements = ListOf(element1, element2, element3); decimal expected = 2181.47941m; // When diff --git a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj index 957c6ca..8caf4e2 100644 --- a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj +++ b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj @@ -1,16 +1,12 @@ - net7.0 - false - 11 - - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -20,14 +16,15 @@ all - - - + + - - + + + + + - diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj index d838b8b..3b06081 100644 --- a/OnixLabs.Core/OnixLabs.Core.csproj +++ b/OnixLabs.Core/OnixLabs.Core.csproj @@ -1,5 +1,4 @@ - net7.0 11 @@ -14,7 +13,6 @@ https://github.com/onix-labs/onixlabs-dotnet 6.0.0 - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb embedded @@ -29,27 +27,20 @@ git https://github.com/onix-labs/onixlabs-dotnet - true - all runtime; build; native; contentfiles; analyzers; buildtransitive - - + - - - + + - - - diff --git a/OnixLabs.Core/Text/Base16.Constants.cs b/OnixLabs.Core/Text/Base16.Constants.cs index 43a2705..640d8b9 100644 --- a/OnixLabs.Core/Text/Base16.Constants.cs +++ b/OnixLabs.Core/Text/Base16.Constants.cs @@ -21,5 +21,5 @@ public readonly partial struct Base16 /// /// Gets an empty value. /// - public static Base16 Empty => Create(Collection.EmptyArray()); + public static Base16 Empty => Create(EmptyArray()); } diff --git a/OnixLabs.Core/Text/Base32.Constants.cs b/OnixLabs.Core/Text/Base32.Constants.cs index b0bfc27..4d1a094 100644 --- a/OnixLabs.Core/Text/Base32.Constants.cs +++ b/OnixLabs.Core/Text/Base32.Constants.cs @@ -26,5 +26,5 @@ public readonly partial struct Base32 /// /// Gets an empty value. /// - public static Base32 Empty => Create(Collection.EmptyArray()); + public static Base32 Empty => Create(EmptyArray()); } diff --git a/OnixLabs.Core/Text/Base58.Constants.cs b/OnixLabs.Core/Text/Base58.Constants.cs index dc7e12e..7d07ef8 100644 --- a/OnixLabs.Core/Text/Base58.Constants.cs +++ b/OnixLabs.Core/Text/Base58.Constants.cs @@ -21,5 +21,5 @@ public readonly partial struct Base58 /// /// Gets an empty value. /// - public static Base58 Empty => Create(Collection.EmptyArray()); + public static Base58 Empty => Create(EmptyArray()); } diff --git a/OnixLabs.Core/Text/Base64.Constants.cs b/OnixLabs.Core/Text/Base64.Constants.cs index a44b4c1..0809bd8 100644 --- a/OnixLabs.Core/Text/Base64.Constants.cs +++ b/OnixLabs.Core/Text/Base64.Constants.cs @@ -21,5 +21,5 @@ public readonly partial struct Base64 /// /// Gets an empty value. /// - public static Base64 Empty => Create(Collection.EmptyArray()); + public static Base64 Empty => Create(EmptyArray()); } diff --git a/OnixLabs.Playground/OnixLabs.Playground.csproj b/OnixLabs.Playground/OnixLabs.Playground.csproj index faf427b..d7a92fd 100644 --- a/OnixLabs.Playground/OnixLabs.Playground.csproj +++ b/OnixLabs.Playground/OnixLabs.Playground.csproj @@ -1,17 +1,16 @@ - Exe net7.0 enable 11 - + + - diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs index 7c01726..df5e492 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs @@ -60,8 +60,8 @@ public void DifferentHashesShouldNotBeConsideredEqual() public void HashesShouldProduceANegativeOneSortOrderWhenTheLeftHandHashIsLessThanTheRightHandHash() { // Arrange - Hash a = Hash.Create(Collection.ArrayOf(1)); - Hash b = Hash.Create(Collection.ArrayOf(2)); + Hash a = Hash.Create(ArrayOf(1)); + Hash b = Hash.Create(ArrayOf(2)); const int expected = -1; // Act @@ -75,8 +75,8 @@ public void HashesShouldProduceANegativeOneSortOrderWhenTheLeftHandHashIsLessTha public void HashesShouldProduceAPositiveOneSortOrderWhenTheLeftHandHashIsGreaterThanTheRightHandHash() { // Arrange - Hash a = Hash.Create(Collection.ArrayOf(2)); - Hash b = Hash.Create(Collection.ArrayOf(1)); + Hash a = Hash.Create(ArrayOf(2)); + Hash b = Hash.Create(ArrayOf(1)); const int expected = 1; // Act @@ -90,8 +90,8 @@ public void HashesShouldProduceAPositiveOneSortOrderWhenTheLeftHandHashIsGreater public void HashesShouldProduceAZeroSortOrderWhenTheLeftHandHashIsEqualToTheRightHandHash() { // Arrange - Hash a = Hash.Create(Collection.ArrayOf(1)); - Hash b = Hash.Create(Collection.ArrayOf(1)); + Hash a = Hash.Create(ArrayOf(1)); + Hash b = Hash.Create(ArrayOf(1)); const int expected = 0; // Act diff --git a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs index bad2f1b..8ea8b61 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs @@ -24,7 +24,7 @@ namespace OnixLabs.Security.Cryptography.UnitTests; public sealed class MerkleTreeGenericTests { - private readonly IEnumerable setA = Collection.EnumerableOf( + private readonly IEnumerable setA = EnumerableOf( new MerkleNode("abc", 123, "1953-05-08T01:00:59Z".ToDateTime(), Guid.Parse("18d1e14c-9762-4b2c-8774-3f053e8579e0")), new MerkleNode("def", 456, "1953-05-08T06:30:00Z".ToDateTime(), Guid.Parse("a5d0ad36-f9a6-4fb0-9374-aa658eb19a51")), new MerkleNode("hij", 789, "1953-05-08T12:00:33Z".ToDateTime(), Guid.Parse("0d324d48-d451-416e-ac4d-fed1a324d446")), @@ -32,7 +32,7 @@ public sealed class MerkleTreeGenericTests new MerkleNode("nop", 112, "1953-05-08T23:00:59Z".ToDateTime(), Guid.Parse("193863c7-3bfa-4a3c-874a-a99d98b38358")) ); - private readonly IEnumerable setB = Collection.EnumerableOf( + private readonly IEnumerable setB = EnumerableOf( new MerkleNode("qrs", 123, "1900-05-08T01:00:59Z".ToDateTime(), Guid.Parse("893576c9-7cb1-4653-a7c4-21e5ba9e7275")), new MerkleNode("tuv", 456, "1901-05-08T06:30:00Z".ToDateTime(), Guid.Parse("e7543a7e-3a52-48f5-842e-9448931f1cde")), new MerkleNode("qxy", 789, "1902-05-08T12:00:33Z".ToDateTime(), Guid.Parse("d228ab75-d36a-4392-9c51-888a5b7f9db7")), diff --git a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj index 0af9b5e..596e207 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj +++ b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj @@ -1,13 +1,9 @@ - net7.0 - false - 11 - @@ -20,10 +16,12 @@ all - - + + + + diff --git a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj index 1abfdb3..9634790 100644 --- a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj +++ b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj @@ -1,5 +1,4 @@ - net7.0 OnixLabs.Security.Cryptography @@ -14,7 +13,6 @@ 6.0.0 11 - $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb embedded @@ -29,26 +27,23 @@ git https://github.com/onix-labs/onixlabs-dotnet - true - all runtime; build; native; contentfiles; analyzers; buildtransitive - - + - + + - From f70357e6e91314b7043f2563d6f4080d61648354 Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Thu, 7 Dec 2023 21:46:12 +0000 Subject: [PATCH 08/14] Updated to .NET 8 (#33) * Updated to .NET 8 * Updated GitHub Actions configuration to use .NET 8.0.x --- .github/workflows/dotnet.yml | 2 +- .../OnixLabs.Core.UnitTests.Data.csproj | 4 +- .../OnixLabs.Core.UnitTests.csproj | 4 +- OnixLabs.Core/Collections/Collection.Empty.cs | 32 +++++++++++--- OnixLabs.Core/Collections/Collection.Of.cs | 44 ++++++++++++++----- OnixLabs.Core/OnixLabs.Core.csproj | 4 +- .../OnixLabs.Playground.csproj | 4 +- OnixLabs.Playground/Program.cs | 5 --- ...ecurity.Cryptography.UnitTests.Data.csproj | 4 +- ...abs.Security.Cryptography.UnitTests.csproj | 4 +- .../OnixLabs.Security.Cryptography.csproj | 4 +- .../Sha3.Permute.cs | 2 + onixlabs-dotnet.sln.DotSettings | 3 +- 13 files changed, 79 insertions(+), 37 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index bbc4192..32f8ed7 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -19,7 +19,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v1 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore - name: Build diff --git a/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj b/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj index 1182a5c..ea9bfbe 100644 --- a/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj +++ b/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj @@ -1,11 +1,13 @@ - net7.0 + net8.0 enable enable false + + 12 diff --git a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj index 8caf4e2..bb2adbb 100644 --- a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj +++ b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj @@ -1,8 +1,8 @@ - net7.0 + net8.0 false - 11 + 12 diff --git a/OnixLabs.Core/Collections/Collection.Empty.cs b/OnixLabs.Core/Collections/Collection.Empty.cs index ecccf14..50cacb4 100644 --- a/OnixLabs.Core/Collections/Collection.Empty.cs +++ b/OnixLabs.Core/Collections/Collection.Empty.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Runtime.CompilerServices; namespace OnixLabs.Core.Collections; @@ -29,6 +30,7 @@ public static partial class Collection /// /// The underlying type of the enumerable. /// Returns an empty enumerable. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static IEnumerable EmptyEnumerable() { return Enumerable.Empty(); @@ -39,6 +41,7 @@ public static IEnumerable EmptyEnumerable() /// /// The underlying type of the array. /// Returns an empty array. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static T[] EmptyArray() { return Array.Empty(); @@ -49,6 +52,7 @@ public static T[] EmptyArray() /// /// The underlying type of the immutable array. /// Returns an empty immutable array. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableArray EmptyImmutableArray() { return ImmutableArray.Empty; @@ -59,9 +63,10 @@ public static ImmutableArray EmptyImmutableArray() /// /// The underlying type of the list. /// Returns an empty list. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static List EmptyList() { - return new List(); + return []; } /// @@ -69,6 +74,7 @@ public static List EmptyList() /// /// The underlying type of the immutable list. /// Returns an empty immutable list. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableList EmptyImmutableList() { return ImmutableList.Empty; @@ -80,9 +86,10 @@ public static ImmutableList EmptyImmutableList() /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns an empty dictionary. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Dictionary EmptyDictionary() where TKey : notnull { - return new Dictionary(); + return []; } /// @@ -91,6 +98,7 @@ public static Dictionary EmptyDictionary() where TKe /// The underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an empty immutable dictionary. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableDictionary EmptyImmutableDictionary() where TKey : notnull { return ImmutableDictionary.Empty; @@ -102,9 +110,10 @@ public static ImmutableDictionary EmptyImmutableDictionaryThe underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns an empty sorted dictionary. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedDictionary EmptySortedDictionary() where TKey : notnull { - return new SortedDictionary(); + return []; } /// @@ -113,6 +122,7 @@ public static SortedDictionary EmptySortedDictionary /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an empty immutable sorted dictionary. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedDictionary EmptyImmutableSortedDictionary() where TKey : notnull { return ImmutableSortedDictionary.Empty; @@ -123,9 +133,10 @@ public static ImmutableSortedDictionary EmptyImmutableSortedDictio /// /// The underlying type of the hash set. /// Returns an empty hash set. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static HashSet EmptyHashSet() { - return new HashSet(); + return []; } /// @@ -133,6 +144,7 @@ public static HashSet EmptyHashSet() /// /// The underlying type of the immutable hash set. /// Returns an empty immutable hash set. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableHashSet EmptyImmutableHashSet() { return ImmutableHashSet.Empty; @@ -143,9 +155,10 @@ public static ImmutableHashSet EmptyImmutableHashSet() /// /// The underlying type of the sorted set. /// Returns an empty sorted set. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedSet EmptySortedSet() { - return new SortedSet(); + return []; } /// @@ -153,6 +166,7 @@ public static SortedSet EmptySortedSet() /// /// The underlying type of the immutable sorted set. /// Returns an empty immutable sorted set. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedSet EmptyImmutableSortedSet() { return ImmutableSortedSet.Empty; @@ -163,9 +177,10 @@ public static ImmutableSortedSet EmptyImmutableSortedSet() /// /// The underlying type of the stack. /// Returns an empty stack. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Stack EmptyStack() { - return new Stack(); + return []; } /// @@ -173,6 +188,7 @@ public static Stack EmptyStack() /// /// The underlying type of the immutable stack. /// Returns an empty immutable stack. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableStack EmptyImmutableStack() { return ImmutableStack.Empty; @@ -183,9 +199,10 @@ public static ImmutableStack EmptyImmutableStack() /// /// The underlying type of the queue. /// Returns an empty queue. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Queue EmptyQueue() { - return new Queue(); + return []; } /// @@ -193,6 +210,7 @@ public static Queue EmptyQueue() /// /// The underlying type of the immutable queue. /// Returns an empty immutable queue. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableQueue EmptyImmutableQueue() { return ImmutableQueue.Empty; diff --git a/OnixLabs.Core/Collections/Collection.Of.cs b/OnixLabs.Core/Collections/Collection.Of.cs index 657aad2..624a841 100644 --- a/OnixLabs.Core/Collections/Collection.Of.cs +++ b/OnixLabs.Core/Collections/Collection.Of.cs @@ -15,6 +15,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Runtime.CompilerServices; namespace OnixLabs.Core.Collections; @@ -26,9 +27,10 @@ public static partial class Collection /// The items which will populate the enumerable. /// The underlying type of the enumerable. /// Returns an enumerable populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static IEnumerable EnumerableOf(params T[] items) { - return items; + return [..items]; } /// @@ -37,9 +39,10 @@ public static IEnumerable EnumerableOf(params T[] items) /// The items which will populate the array. /// The underlying type of the array. /// Returns an array populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static T[] ArrayOf(params T[] items) { - return items; + return [..items]; } /// @@ -48,9 +51,10 @@ public static T[] ArrayOf(params T[] items) /// The items which will populate the immutable array. /// The underlying type of the immutable array. /// Returns an immutable array populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableArray ImmutableArrayOf(params T[] items) { - return ImmutableArray.Create(items); + return [..items]; } /// @@ -59,9 +63,10 @@ public static ImmutableArray ImmutableArrayOf(params T[] items) /// The items which will populate the list. /// The underlying type of the list. /// Returns a list populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static List ListOf(params T[] items) { - return new List(items); + return [..items]; } /// @@ -70,9 +75,10 @@ public static List ListOf(params T[] items) /// The items which will populate the immutable list. /// The underlying type of the immutable list. /// Returns an immutable list populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableList ImmutableListOf(params T[] items) { - return ImmutableList.Create(items); + return [..items]; } /// @@ -82,6 +88,7 @@ public static ImmutableList ImmutableListOf(params T[] items) /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns a dictionary populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Dictionary DictionaryOf(params KeyValuePair[] items) where TKey : notnull { return new Dictionary(items); @@ -94,6 +101,7 @@ public static Dictionary DictionaryOf(params KeyValu /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns a dictionary populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Dictionary DictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull { return DictionaryOf(items.Select(item => new KeyValuePair(item.key, item.value)).ToArray()); @@ -106,6 +114,7 @@ public static Dictionary DictionaryOf(params (TKey k /// The underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an immutable dictionary populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableDictionary ImmutableDictionaryOf( params KeyValuePair[] items) where TKey : notnull { @@ -119,6 +128,7 @@ public static ImmutableDictionary ImmutableDictionaryOfThe underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an immutable dictionary populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableDictionary ImmutableDictionaryOf( params (TKey key, TValue value)[] items) where TKey : notnull { @@ -132,6 +142,7 @@ public static ImmutableDictionary ImmutableDictionaryOfThe underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns a sorted dictionary populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedDictionary SortedDictionaryOf( params KeyValuePair[] items) where TKey : notnull { @@ -145,6 +156,7 @@ public static SortedDictionary SortedDictionaryOf( /// The underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns a sorted dictionary populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedDictionary SortedDictionaryOf( params (TKey key, TValue value)[] items) where TKey : notnull { @@ -158,6 +170,7 @@ public static SortedDictionary SortedDictionaryOf( /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an immutable sorted dictionary populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( params KeyValuePair[] items) where TKey : notnull { @@ -171,6 +184,7 @@ public static ImmutableSortedDictionary ImmutableSortedDictionaryO /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an immutable sorted dictionary populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( params (TKey key, TValue value)[] items) where TKey : notnull { @@ -183,9 +197,10 @@ public static ImmutableSortedDictionary ImmutableSortedDictionaryO /// The items which will populate the hash set. /// The underlying type of the hash set. /// Returns a hash set populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static HashSet HashSetOf(params T[] items) { - return new HashSet(items); + return [..items]; } /// @@ -194,9 +209,10 @@ public static HashSet HashSetOf(params T[] items) /// The items which will populate the immutable hash set. /// The underlying type of the immutable hash set. /// Returns an immutable hash set populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableHashSet ImmutableHashSetOf(params T[] items) { - return ImmutableHashSet.Create(items); + return [..items]; } /// @@ -205,9 +221,10 @@ public static ImmutableHashSet ImmutableHashSetOf(params T[] items) /// The items which will populate the sorted set. /// The underlying type of the sorted set. /// Returns a sorted set populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedSet SortedSetOf(params T[] items) { - return new SortedSet(items); + return [..items]; } /// @@ -216,9 +233,10 @@ public static SortedSet SortedSetOf(params T[] items) /// The items which will populate the immutable sorted set. /// The underlying type of the immutable sorted set. /// Returns an immutable sorted set populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) { - return ImmutableSortedSet.Create(items); + return [..items]; } /// @@ -227,6 +245,7 @@ public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) /// The items which will populate the stack. /// The underlying type of the stack. /// Returns a stack populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Stack StackOf(params T[] items) { return new Stack(items); @@ -238,9 +257,10 @@ public static Stack StackOf(params T[] items) /// The items which will populate the immutable stack. /// The underlying type of the immutable stack. /// Returns an immutable stack populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableStack ImmutableStackOf(params T[] items) { - return ImmutableStack.Create(items); + return [..items]; } /// @@ -249,6 +269,7 @@ public static ImmutableStack ImmutableStackOf(params T[] items) /// The items which will populate the queue. /// The underlying type of the queue. /// Returns a queue populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Queue QueueOf(params T[] items) { return new Queue(items); @@ -260,8 +281,9 @@ public static Queue QueueOf(params T[] items) /// The items which will populate the immutable queue. /// The underlying type of the immutable queue. /// Returns an immutable queue populated with the specified items. + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableQueue ImmutableQueueOf(params T[] items) { - return ImmutableQueue.Create(items); + return [..items]; } } diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj index 3b06081..6c4ab47 100644 --- a/OnixLabs.Core/OnixLabs.Core.csproj +++ b/OnixLabs.Core/OnixLabs.Core.csproj @@ -1,7 +1,7 @@ - net7.0 - 11 + net8.0 + 12 enable true OnixLabs.Core diff --git a/OnixLabs.Playground/OnixLabs.Playground.csproj b/OnixLabs.Playground/OnixLabs.Playground.csproj index d7a92fd..2e0890c 100644 --- a/OnixLabs.Playground/OnixLabs.Playground.csproj +++ b/OnixLabs.Playground/OnixLabs.Playground.csproj @@ -1,9 +1,9 @@ Exe - net7.0 + net8.0 enable - 11 + 12 diff --git a/OnixLabs.Playground/Program.cs b/OnixLabs.Playground/Program.cs index ab33f8f..6674ac3 100644 --- a/OnixLabs.Playground/Program.cs +++ b/OnixLabs.Playground/Program.cs @@ -12,16 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using OnixLabs.Core.Units; - namespace OnixLabs.Playground; internal static class Program { public static void Main() { - DataSize ds = DataSize.FromBytes(1026.0); - Console.WriteLine(ds.ToString("KiB")); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj b/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj index 8096231..c4fe399 100644 --- a/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj @@ -1,11 +1,13 @@ - net7.0 + net8.0 enable enable false + + 12 diff --git a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj index 596e207..5aba4ae 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj +++ b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj @@ -1,8 +1,8 @@ - net7.0 + net8.0 false - 11 + 12 diff --git a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj index 9634790..ace5d43 100644 --- a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj +++ b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj @@ -1,6 +1,6 @@ - net7.0 + net8.0 OnixLabs.Security.Cryptography ONIXLabs ONIXLabs Cryptography API for .NET @@ -11,7 +11,7 @@ Copyright © ONIXLabs 2020-2023 https://github.com/onix-labs/onixlabs-dotnet 6.0.0 - 11 + 12 $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb diff --git a/OnixLabs.Security.Cryptography/Sha3.Permute.cs b/OnixLabs.Security.Cryptography/Sha3.Permute.cs index 3af16ff..5021217 100644 --- a/OnixLabs.Security.Cryptography/Sha3.Permute.cs +++ b/OnixLabs.Security.Cryptography/Sha3.Permute.cs @@ -47,6 +47,8 @@ private static void Permute(ulong[] state) Iota(round); } + return; + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] void Theta() { diff --git a/onixlabs-dotnet.sln.DotSettings b/onixlabs-dotnet.sln.DotSettings index 4b838e7..78825e9 100644 --- a/onixlabs-dotnet.sln.DotSettings +++ b/onixlabs-dotnet.sln.DotSettings @@ -1,5 +1,5 @@  - Copyright 2020-$CURRENT_YEAR$ ONIXLabs + Copyright 2020-${CurrentDate.Year} ONIXLabs Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + True True True True From 4228813cfdee93852e0d966fd6d13d4d6a472e8f Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Fri, 5 Apr 2024 23:11:54 +0100 Subject: [PATCH 09/14] feature/numerics (#34) Implemented OnixLabs.Numerics package, including BigDecimal, NumberInfo, and generic math extensions. --- .editorconfig | 12 +- .idea/.idea.onixlabs-dotnet/.idea/vcs.xml | 2 +- .../OnixLabs.Core.UnitTests.Data.csproj | 8 +- .../Linq/IEnumerableExtensionTests.cs | 64 +- .../OnixLabs.Core.UnitTests.csproj | 11 +- .../Text/StringBuilderExtensionTests.cs | 152 +++ .../Units/DataSizeTests.cs | 835 --------------- .../Units/TemperatureTests.cs | 470 --------- OnixLabs.Core/Collections/Collection.Empty.cs | 24 +- OnixLabs.Core/Collections/Collection.Of.cs | 28 +- OnixLabs.Core/Extensions.Object.cs | 2 +- OnixLabs.Core/Extensions.String.cs | 42 +- OnixLabs.Core/Linq/Extensions.IEnumerable.cs | 30 +- OnixLabs.Core/Numerics/GenericMath.cs | 43 - OnixLabs.Core/Preconditions.cs | 27 +- OnixLabs.Core/Text/StringBuilderExtensions.cs | 151 +++ OnixLabs.Core/Units/DataSize.Arithmetic.cs | 106 -- OnixLabs.Core/Units/DataSize.Constants.cs | 63 -- OnixLabs.Core/Units/DataSize.Equatable.cs | 82 -- OnixLabs.Core/Units/DataSize.From.cs | 424 -------- .../Units/DataSize.Static.Arithmetic.cs | 71 -- .../Units/DataSize.Static.Comparison.cs | 45 - OnixLabs.Core/Units/DataSize.Static.From.cs | 438 -------- OnixLabs.Core/Units/DataSize.To.cs | 185 ---- OnixLabs.Core/Units/DataSize.cs | 247 ----- OnixLabs.Core/Units/Temperature.Arithmetic.cs | 106 -- OnixLabs.Core/Units/Temperature.Equatable.cs | 82 -- OnixLabs.Core/Units/Temperature.From.cs | 88 -- .../Units/Temperature.Static.Arithmetic.cs | 71 -- .../Units/Temperature.Static.Comparison.cs | 45 - .../Units/Temperature.Static.From.cs | 97 -- OnixLabs.Core/Units/Temperature.To.cs | 92 -- OnixLabs.Core/Units/Temperature.cs | 68 -- .../BigDecimalArithmeticAbsDataAttribute.cs | 27 + ...gDecimalArithmeticAdditionDataAttribute.cs | 32 + ...gDecimalArithmeticDivisionDataAttribute.cs | 40 + ...igDecimalArithmeticModulusDataAttribute.cs | 28 + ...alArithmeticMultiplicationDataAttribute.cs | 32 + .../BigDecimalArithmeticPowDataAttribute.cs | 205 ++++ .../BigDecimalArithmeticRoundDataAttribute.cs | 35 + .../BigDecimalArithmeticScaleDataAttribute.cs | 59 ++ ...cimalArithmeticSubtractionDataAttribute.cs | 32 + .../BigDecimalArithmeticTrimDataAttribute.cs | 42 + ...gDecimalArithmeticTruncateDataAttribute.cs | 30 + ...malArithmeticUnaryAdditionDataAttribute.cs | 27 + ...ArithmeticUnarySubtractionDataAttribute.cs | 27 + .../BigDecimalIeee754BinaryDataAttribute.cs | 217 ++++ .../BigDecimalIeee754DecimalDataAttribute.cs | 915 +++++++++++++++++ .../BigDecimalIsDataAttribute.cs | 33 + .../BigDecimalWriteDataAttribute.cs | 27 + .../NumberFormatDataAttribute.cs | 37 + ...NumberInfoEqualityComparerDataAttribute.cs | 35 + ...mberInfoOrdinalityComparerDataAttribute.cs | 35 + ...umericsExtensionsToDecimalDataAttribute.cs | 466 +++++++++ ...ensionsToNumberInfoDecimalDataAttribute.cs | 133 +++ ...tensionsToNumberInfoDoubleDataAttribute.cs | 93 ++ ...xtensionsToNumberInfoFloatDataAttribute.cs | 90 ++ ...ensionsToNumberInfoIntegerDataAttribute.cs | 95 ++ .../OnixLabs.Numerics.UnitTests.Data.csproj | 29 + .../TestDataGenerator.cs | 952 ++++++++++++++++++ .../BigDecimalArithmeticAbsTests.cs | 35 + .../BigDecimalArithmeticAdditionTests.cs | 35 + .../BigDecimalArithmeticDecrementTests.cs | 52 + .../BigDecimalArithmeticDivisionTests.cs | 60 ++ .../BigDecimalArithmeticIncrementTests.cs | 52 + .../BigDecimalArithmeticModulusTests.cs | 35 + ...BigDecimalArithmeticMultiplicationTests.cs | 35 + .../BigDecimalArithmeticPowTests.cs | 32 + .../BigDecimalArithmeticRoundTests.cs | 35 + .../BigDecimalArithmeticScaleTests.cs | 32 + .../BigDecimalArithmeticSubtractionTests.cs | 35 + .../BigDecimalArithmeticTrimTests.cs | 32 + .../BigDecimalArithmeticTruncateTests.cs | 35 + .../BigDecimalArithmeticUnaryAdditionTests.cs | 35 + ...gDecimalArithmeticUnarySubtractionTests.cs | 35 + .../BigDecimalComparableMinMaxTests.cs | 167 +++ .../BigDecimalConstantTests.cs | 134 +++ .../BigDecimalConstructorBigIntegerTests.cs | 76 ++ .../BigDecimalConstructorByteTests.cs | 59 ++ .../BigDecimalConstructorDoubleBinaryTests.cs | 37 + ...BigDecimalConstructorDoubleDecimalTests.cs | 37 + .../BigDecimalConstructorInt16Tests.cs | 59 ++ .../BigDecimalConstructorInt32Tests.cs | 83 ++ .../BigDecimalConstructorInt64Tests.cs | 59 ++ .../BigDecimalConstructorSByteTests.cs | 59 ++ .../BigDecimalConstructorUInt16Tests.cs | 59 ++ .../BigDecimalConstructorUInt32Tests.cs | 59 ++ .../BigDecimalConstructorUInt64Tests.cs | 59 ++ .../BigDecimalEqualityComparerTests.cs | 57 ++ .../BigDecimalFormatTests.cs | 97 ++ .../BigDecimalIsTests.cs | 105 ++ .../BigDecimalOrdinalityComparerTests.cs | 129 +++ .../BigDecimalParseTests.cs | 96 ++ .../BigDecimalToStringTests.cs | 97 ++ .../BigDecimalWriteTests.cs | 129 +++ .../GenericMathDeltaTests.cs | 67 ++ .../GenericMathIntegerLengthTests.cs | 269 +++++ .../GenericMathMinMaxTests.cs | 44 + .../NumberInfoConstantTests.cs | 90 ++ .../NumberInfoEqualityComparerTests.cs | 57 ++ .../NumberInfoOrdinalityComparerTests.cs | 129 +++ .../NumberInfoParseTests.cs | 112 +++ .../NumberInfoToStringTests.cs | 37 + .../NumericsExtensionsTests.cs | 230 +++++ .../OnixLabs.Numerics.UnitTests.csproj | 30 + .../BigDecimal.Arithmetic.Abs.cs | 30 + .../BigDecimal.Arithmetic.Addition.cs | 50 + .../BigDecimal.Arithmetic.Decrement.cs | 50 + .../BigDecimal.Arithmetic.Division.cs | 80 ++ .../BigDecimal.Arithmetic.Increment.cs | 53 + .../BigDecimal.Arithmetic.Modulus.cs | 47 + .../BigDecimal.Arithmetic.Multiplication.cs | 47 + .../BigDecimal.Arithmetic.Pow.cs | 45 + .../BigDecimal.Arithmetic.Round.cs | 98 ++ .../BigDecimal.Arithmetic.Scale.cs | 66 ++ .../BigDecimal.Arithmetic.Subtraction.cs | 50 + .../BigDecimal.Arithmetic.Trim.cs | 43 + .../BigDecimal.Arithmetic.Truncate.cs | 27 + .../BigDecimal.Arithmetic.UnaryAddition.cs | 38 + .../BigDecimal.Arithmetic.UnarySubtraction.cs | 38 + .../BigDecimal.Comparable.MinMax.cs | 158 +++ .../BigDecimal.Comparable.cs | 64 +- OnixLabs.Numerics/BigDecimal.Constants.cs | 93 ++ OnixLabs.Numerics/BigDecimal.Convert.cs | 233 +++++ .../BigDecimal.Convertible.Explicit.cs | 207 ++++ .../BigDecimal.Convertible.Implicit.cs | 161 +++ OnixLabs.Numerics/BigDecimal.Convertible.cs | 191 ++++ OnixLabs.Numerics/BigDecimal.Equatable.cs | 122 +++ OnixLabs.Numerics/BigDecimal.Format.cs | 45 + OnixLabs.Numerics/BigDecimal.Get.cs | 40 + OnixLabs.Numerics/BigDecimal.Is.cs | 190 ++++ OnixLabs.Numerics/BigDecimal.Parse.cs | 169 ++++ OnixLabs.Numerics/BigDecimal.To.cs | 103 ++ OnixLabs.Numerics/BigDecimal.Write.cs | 76 ++ OnixLabs.Numerics/BigDecimal.cs | 82 ++ .../BigDecimalEqualityComparer.cs | 117 +++ .../BigDecimalOrdinalityComparer.cs | 114 +++ OnixLabs.Numerics/ConversionMode.cs | 31 + OnixLabs.Numerics/GenericMath.cs | 63 ++ OnixLabs.Numerics/Ieee754Converter.cs | 228 +++++ .../NumberInfo.Comparable.cs | 55 +- OnixLabs.Numerics/NumberInfo.Constants.cs | 50 + OnixLabs.Numerics/NumberInfo.Equatable.cs | 122 +++ OnixLabs.Numerics/NumberInfo.Parse.cs | 161 +++ OnixLabs.Numerics/NumberInfo.To.cs | 54 + OnixLabs.Numerics/NumberInfo.cs | 109 ++ .../NumberInfoEqualityComparer.cs | 118 +++ .../NumberInfoFormatter.FormatCurrency.cs | 119 +++ .../NumberInfoFormatter.FormatDecimal.cs | 28 + .../NumberInfoFormatter.FormatExponential.cs | 42 + .../NumberInfoFormatter.FormatFixed.cs | 24 +- .../NumberInfoFormatter.FormatGeneral.cs | 28 + .../NumberInfoFormatter.FormatNumber.cs | 58 ++ .../NumberInfoFormatter.FormatPercentage.cs | 104 ++ OnixLabs.Numerics/NumberInfoFormatter.cs | 124 +++ .../NumberInfoOrdinalityComparer.cs | 119 +++ .../NumberInfoParser.Sanitize.cs | 142 +++ .../NumberInfoParser.SanitizeCurrency.cs | 138 +++ .../NumberInfoParser.SanitizeNumber.cs | 76 ++ OnixLabs.Numerics/NumberInfoParser.cs | 119 +++ OnixLabs.Numerics/NumericsExtensions.cs | 212 ++++ OnixLabs.Numerics/OnixLabs.Numerics.csproj | 49 + OnixLabs.Numerics/ScaleMode.cs | 31 + .../OnixLabs.Playground.csproj | 5 + OnixLabs.Playground/Program.cs | 8 +- ...ecurity.Cryptography.UnitTests.Data.csproj | 8 +- ...abs.Security.Cryptography.UnitTests.csproj | 8 +- .../Sha3.Permute.cs | 16 +- onixlabs-dotnet.sln | 47 +- onixlabs-dotnet.sln.DotSettings | 2 + 170 files changed, 12840 insertions(+), 3866 deletions(-) create mode 100644 OnixLabs.Core.UnitTests/Text/StringBuilderExtensionTests.cs delete mode 100644 OnixLabs.Core.UnitTests/Units/DataSizeTests.cs delete mode 100644 OnixLabs.Core.UnitTests/Units/TemperatureTests.cs delete mode 100644 OnixLabs.Core/Numerics/GenericMath.cs create mode 100644 OnixLabs.Core/Text/StringBuilderExtensions.cs delete mode 100644 OnixLabs.Core/Units/DataSize.Arithmetic.cs delete mode 100644 OnixLabs.Core/Units/DataSize.Constants.cs delete mode 100644 OnixLabs.Core/Units/DataSize.Equatable.cs delete mode 100644 OnixLabs.Core/Units/DataSize.From.cs delete mode 100644 OnixLabs.Core/Units/DataSize.Static.Arithmetic.cs delete mode 100644 OnixLabs.Core/Units/DataSize.Static.Comparison.cs delete mode 100644 OnixLabs.Core/Units/DataSize.Static.From.cs delete mode 100644 OnixLabs.Core/Units/DataSize.To.cs delete mode 100644 OnixLabs.Core/Units/DataSize.cs delete mode 100644 OnixLabs.Core/Units/Temperature.Arithmetic.cs delete mode 100644 OnixLabs.Core/Units/Temperature.Equatable.cs delete mode 100644 OnixLabs.Core/Units/Temperature.From.cs delete mode 100644 OnixLabs.Core/Units/Temperature.Static.Arithmetic.cs delete mode 100644 OnixLabs.Core/Units/Temperature.Static.Comparison.cs delete mode 100644 OnixLabs.Core/Units/Temperature.Static.From.cs delete mode 100644 OnixLabs.Core/Units/Temperature.To.cs delete mode 100644 OnixLabs.Core/Units/Temperature.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticAbsDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticAdditionDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticDivisionDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticModulusDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticMultiplicationDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticPowDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticRoundDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticScaleDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticSubtractionDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticTrimDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticTruncateDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticUnaryAdditionDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticUnarySubtractionDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalIeee754BinaryDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalIeee754DecimalDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalIsDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/BigDecimalWriteDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/NumberFormatDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/NumberInfoEqualityComparerDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/NumberInfoOrdinalityComparerDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToDecimalDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoDecimalDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoDoubleDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoFloatDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoIntegerDataAttribute.cs create mode 100644 OnixLabs.Numerics.UnitTests.Data/OnixLabs.Numerics.UnitTests.Data.csproj create mode 100644 OnixLabs.Numerics.UnitTests.Data/TestDataGenerator.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticAbsTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticAdditionTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticDecrementTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticDivisionTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticIncrementTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticModulusTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticMultiplicationTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticPowTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticRoundTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticScaleTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticSubtractionTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticTrimTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticTruncateTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticUnaryAdditionTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalArithmeticUnarySubtractionTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalComparableMinMaxTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstantTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorBigIntegerTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorByteTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorDoubleBinaryTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorDoubleDecimalTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt16Tests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt32Tests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt64Tests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorSByteTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt16Tests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt32Tests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt64Tests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalEqualityComparerTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalFormatTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalIsTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalOrdinalityComparerTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalParseTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalToStringTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/BigDecimalWriteTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/GenericMathDeltaTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/GenericMathIntegerLengthTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/GenericMathMinMaxTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/NumberInfoConstantTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/NumberInfoEqualityComparerTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/NumberInfoOrdinalityComparerTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/NumberInfoParseTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/NumberInfoToStringTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/NumericsExtensionsTests.cs create mode 100644 OnixLabs.Numerics.UnitTests/OnixLabs.Numerics.UnitTests.csproj create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Abs.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Addition.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Decrement.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Division.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Increment.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Modulus.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Multiplication.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Pow.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Round.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Scale.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Subtraction.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Trim.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.Truncate.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.UnaryAddition.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Arithmetic.UnarySubtraction.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Comparable.MinMax.cs rename OnixLabs.Core/Units/DataSize.Comparable.cs => OnixLabs.Numerics/BigDecimal.Comparable.cs (63%) create mode 100644 OnixLabs.Numerics/BigDecimal.Constants.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Convert.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Convertible.Explicit.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Convertible.Implicit.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Convertible.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Equatable.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Format.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Get.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Is.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Parse.cs create mode 100644 OnixLabs.Numerics/BigDecimal.To.cs create mode 100644 OnixLabs.Numerics/BigDecimal.Write.cs create mode 100644 OnixLabs.Numerics/BigDecimal.cs create mode 100644 OnixLabs.Numerics/BigDecimalEqualityComparer.cs create mode 100644 OnixLabs.Numerics/BigDecimalOrdinalityComparer.cs create mode 100644 OnixLabs.Numerics/ConversionMode.cs create mode 100644 OnixLabs.Numerics/GenericMath.cs create mode 100644 OnixLabs.Numerics/Ieee754Converter.cs rename OnixLabs.Core/Units/Temperature.Comparable.cs => OnixLabs.Numerics/NumberInfo.Comparable.cs (62%) create mode 100644 OnixLabs.Numerics/NumberInfo.Constants.cs create mode 100644 OnixLabs.Numerics/NumberInfo.Equatable.cs create mode 100644 OnixLabs.Numerics/NumberInfo.Parse.cs create mode 100644 OnixLabs.Numerics/NumberInfo.To.cs create mode 100644 OnixLabs.Numerics/NumberInfo.cs create mode 100644 OnixLabs.Numerics/NumberInfoEqualityComparer.cs create mode 100644 OnixLabs.Numerics/NumberInfoFormatter.FormatCurrency.cs create mode 100644 OnixLabs.Numerics/NumberInfoFormatter.FormatDecimal.cs create mode 100644 OnixLabs.Numerics/NumberInfoFormatter.FormatExponential.cs rename OnixLabs.Core/Units/Temperature.Constants.cs => OnixLabs.Numerics/NumberInfoFormatter.FormatFixed.cs (64%) create mode 100644 OnixLabs.Numerics/NumberInfoFormatter.FormatGeneral.cs create mode 100644 OnixLabs.Numerics/NumberInfoFormatter.FormatNumber.cs create mode 100644 OnixLabs.Numerics/NumberInfoFormatter.FormatPercentage.cs create mode 100644 OnixLabs.Numerics/NumberInfoFormatter.cs create mode 100644 OnixLabs.Numerics/NumberInfoOrdinalityComparer.cs create mode 100644 OnixLabs.Numerics/NumberInfoParser.Sanitize.cs create mode 100644 OnixLabs.Numerics/NumberInfoParser.SanitizeCurrency.cs create mode 100644 OnixLabs.Numerics/NumberInfoParser.SanitizeNumber.cs create mode 100644 OnixLabs.Numerics/NumberInfoParser.cs create mode 100644 OnixLabs.Numerics/NumericsExtensions.cs create mode 100644 OnixLabs.Numerics/OnixLabs.Numerics.csproj create mode 100644 OnixLabs.Numerics/ScaleMode.cs diff --git a/.editorconfig b/.editorconfig index 9e4210f..1c42688 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,13 @@ root = true [*] -max_line_length = 140 -insert_final_newline = true \ No newline at end of file +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 +continuation_indent_size = 4 +max_line_length = 140 + +# ReSharper properties +resharper_csharp_wrap_lines = false diff --git a/.idea/.idea.onixlabs-dotnet/.idea/vcs.xml b/.idea/.idea.onixlabs-dotnet/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/.idea.onixlabs-dotnet/.idea/vcs.xml +++ b/.idea/.idea.onixlabs-dotnet/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj b/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj index ea9bfbe..6736305 100644 --- a/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj +++ b/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj @@ -11,13 +11,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs index 863697b..5eeac5e 100644 --- a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,8 +14,8 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; -using OnixLabs.Core.Collections; using OnixLabs.Core.Linq; using OnixLabs.Core.UnitTests.Data.Objects; using Xunit; @@ -444,4 +444,60 @@ public void WhereNotNullShouldProduceExpectedResult() // Then Assert.Equal(expected, actual); } + + [Fact(DisplayName = "IEnumerable.ToCollectionString should produce expected result (Object)")] + public void ToCollectionStringShouldProduceExpectedResultObject() + { + // Given + object[] values = [123, "abc", true, 123.456]; + const string expected = "[123, abc, True, 123.456]"; + + // When + string actual = values.ToCollectionString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.ToCollectionString should produce expected result (String)")] + public void ToCollectionStringShouldProduceExpectedResultString() + { + // Given + string[] values = ["abc", "xyz", "123"]; + const string expected = "[abc, xyz, 123]"; + + // When + string actual = values.ToCollectionString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.ToCollectionString should produce expected result (Int32)")] + public void ToCollectionStringShouldProduceExpectedResultInt32() + { + // Given + int[] values = [0, 1, 12, 123, 1234, -1, -12, -123, -1234]; + const string expected = "[0, 1, 12, 123, 1234, -1, -12, -123, -1234]"; + + // When + string actual = values.ToCollectionString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IEnumerable.ToCollectionString should produce expected result (Int32, IFormattable)")] + public void ToCollectionStringShouldProduceExpectedResultInt32IFormattable() + { + // Given + int[] values = [0, 1, 12, 123, 1234, -1, -12, -123, -1234]; + const string expected = "[£0.00, £1.00, £12.00, £123.00, £1,234.00, -£1.00, -£12.00, -£123.00, -£1,234.00]"; + + // When + string actual = values.ToCollectionString("C", CultureInfo.GetCultureInfo("en-GB")); + + // Then + Assert.Equal(expected, actual); + } } diff --git a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj index bb2adbb..c03520d 100644 --- a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj +++ b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj @@ -5,13 +5,13 @@ 12 - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -20,9 +20,6 @@ - - - diff --git a/OnixLabs.Core.UnitTests/Text/StringBuilderExtensionTests.cs b/OnixLabs.Core.UnitTests/Text/StringBuilderExtensionTests.cs new file mode 100644 index 0000000..815d442 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/StringBuilderExtensionTests.cs @@ -0,0 +1,152 @@ +// Copyright 2020-2023 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class StringBuilderExtensionTests +{ + [Fact(DisplayName = "StringBuilder.Append should produce the expected result")] + public void StringBuilderAppendShouldProduceTheExpectedResult() + { + // Given + StringBuilder builder = new("ABC"); + + // When + builder.Append("XYZ", 123, false); + + // Then + Assert.Equal("ABCXYZ123False", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.Prepend should produce the expected result")] + public void StringBuilderPrependShouldProduceTheExpectedResult() + { + // Given + StringBuilder builder = new("ABC"); + + // When + builder.Prepend("XYZ", 123, false); + + // Then + Assert.Equal("XYZ123FalseABC", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.Trim should produce the expected result (char)")] + public void StringBuilderTrimShouldProduceTheExpectedResultChar() + { + // Given + StringBuilder builder = new("###ABC###"); + + // When + builder.Trim('#'); + + // Then + Assert.Equal("ABC", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.TrimEnd should produce the expected result (char)")] + public void StringBuilderTrimEndShouldProduceTheExpectedResultChar() + { + // Given + StringBuilder builder = new("###ABC###"); + + // When + builder.TrimEnd('#'); + + // Then + Assert.Equal("###ABC", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.TrimStart should produce the expected result (char)")] + public void StringBuilderTrimStartShouldProduceTheExpectedResultChar() + { + // Given + StringBuilder builder = new("###ABC###"); + + // When + builder.TrimStart('#'); + + // Then + Assert.Equal("ABC###", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.Trim should produce the expected result (string)")] + public void StringBuilderTrimShouldProduceTheExpectedResultString() + { + // Given + StringBuilder builder = new("#-#ABC#-#"); + + // When + builder.Trim("#-#"); + + // Then + Assert.Equal("ABC", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.TrimEnd should produce the expected result (string)")] + public void StringBuilderTrimEndShouldProduceTheExpectedResultString() + { + // Given + StringBuilder builder = new("#-#ABC#-#"); + + // When + builder.TrimEnd("#-#"); + + // Then + Assert.Equal("#-#ABC", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.TrimStart should produce the expected result (string)")] + public void StringBuilderTrimStartShouldProduceTheExpectedResultString() + { + // Given + StringBuilder builder = new("#-#ABC#-#"); + + // When + builder.TrimStart("#-#"); + + // Then + Assert.Equal("ABC#-#", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.Wrap should produce the expected result (char)")] + public void StringBuilderWrapShouldProduceTheExpectedResultChar() + { + // Given + StringBuilder builder = new("ABC"); + + // When + builder.Wrap('(', ')'); + + // Then + Assert.Equal("(ABC)", builder.ToString()); + } + + [Fact(DisplayName = "StringBuilder.Wrap should produce the expected result (string)")] + public void StringBuilderWrapShouldProduceTheExpectedResultString() + { + // Given + StringBuilder builder = new("ABC"); + + // When + builder.Wrap("123", "XYZ"); + + // Then + Assert.Equal("123ABCXYZ", builder.ToString()); + } +} diff --git a/OnixLabs.Core.UnitTests/Units/DataSizeTests.cs b/OnixLabs.Core.UnitTests/Units/DataSizeTests.cs deleted file mode 100644 index 9e5f1b7..0000000 --- a/OnixLabs.Core.UnitTests/Units/DataSizeTests.cs +++ /dev/null @@ -1,835 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Units; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Units; - -public sealed class DataSizeTests -{ - [Theory(DisplayName = "DataSize.FromNibbles should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 4)] - [InlineData(2, 8)] - [InlineData(3, 12)] - [InlineData(4, 16)] - [InlineData(5, 20)] - [InlineData(6, 24)] - [InlineData(7, 28)] - [InlineData(8, 32)] - [InlineData(9, 36)] - [InlineData(10, 40)] - public void DataSizeFromNibblesShouldProduceTheExpectedConversionResults(double nibbles, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromNibbles(nibbles); - - // Assert - Assert.Equal(nibbles, dataSize.Nibbles); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8)] - [InlineData(2, 16)] - [InlineData(3, 24)] - [InlineData(4, 32)] - [InlineData(5, 40)] - [InlineData(6, 48)] - [InlineData(7, 56)] - [InlineData(8, 64)] - [InlineData(9, 72)] - [InlineData(10, 80)] - public void DataSizeFromBytesShouldProduceTheExpectedConversionResults(double bytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromBytes(bytes); - - // Assert - Assert.Equal(bytes, dataSize.Bytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromWords should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 16)] - [InlineData(2, 32)] - [InlineData(3, 48)] - [InlineData(4, 64)] - [InlineData(5, 80)] - [InlineData(6, 96)] - [InlineData(7, 112)] - [InlineData(8, 128)] - [InlineData(9, 144)] - [InlineData(10, 160)] - public void DataSizeFromWordsShouldProduceTheExpectedConversionResults(double words, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromWords(words); - - // Assert - Assert.Equal(words, dataSize.Words); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromDoubleWords should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 32)] - [InlineData(2, 64)] - [InlineData(3, 96)] - [InlineData(4, 128)] - [InlineData(5, 160)] - [InlineData(6, 192)] - [InlineData(7, 224)] - [InlineData(8, 256)] - [InlineData(9, 288)] - [InlineData(10, 320)] - public void DataSizeFromDoubleWordsShouldProduceTheExpectedConversionResults(double doubleWords, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromDoubleWords(doubleWords); - - // Assert - Assert.Equal(doubleWords, dataSize.DoubleWords); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromQuadWords should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 64)] - [InlineData(2, 128)] - [InlineData(3, 192)] - [InlineData(4, 256)] - [InlineData(5, 320)] - [InlineData(6, 384)] - [InlineData(7, 448)] - [InlineData(8, 512)] - [InlineData(9, 576)] - [InlineData(10, 640)] - public void DataSizeFromQuadWordsShouldProduceTheExpectedConversionResults(double quadWords, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromQuadWords(quadWords); - - // Assert - Assert.Equal(quadWords, dataSize.QuadWords); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromKiloBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1000)] - [InlineData(2, 2000)] - [InlineData(3, 3000)] - [InlineData(4, 4000)] - [InlineData(5, 5000)] - [InlineData(6, 6000)] - [InlineData(7, 7000)] - [InlineData(8, 8000)] - [InlineData(9, 9000)] - [InlineData(10, 10000)] - public void DataSizeFromKiloBitsShouldProduceTheExpectedConversionResults(double kiloBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromKiloBits(kiloBits); - - // Assert - Assert.Equal(kiloBits, dataSize.KiloBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromKibiBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1024)] - [InlineData(2, 2048)] - [InlineData(3, 3072)] - [InlineData(4, 4096)] - [InlineData(5, 5120)] - [InlineData(6, 6144)] - [InlineData(7, 7168)] - [InlineData(8, 8192)] - [InlineData(9, 9216)] - [InlineData(10, 10240)] - public void DataSizeFromKibiBitsShouldProduceTheExpectedConversionResults(double kibiBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromKibiBits(kibiBits); - - // Assert - Assert.Equal(kibiBits, dataSize.KibiBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromKiloBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8000)] - [InlineData(2, 16000)] - [InlineData(3, 24000)] - [InlineData(4, 32000)] - [InlineData(5, 40000)] - [InlineData(6, 48000)] - [InlineData(7, 56000)] - [InlineData(8, 64000)] - [InlineData(9, 72000)] - [InlineData(10, 80000)] - public void DataSizeFromKiloBytesShouldProduceTheExpectedConversionResults(double kiloBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromKiloBytes(kiloBytes); - - // Assert - Assert.Equal(kiloBytes, dataSize.KiloBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromKibiBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8192)] - [InlineData(2, 16384)] - [InlineData(3, 24576)] - [InlineData(4, 32768)] - [InlineData(5, 40960)] - [InlineData(6, 49152)] - [InlineData(7, 57344)] - [InlineData(8, 65536)] - [InlineData(9, 73728)] - [InlineData(10, 81920)] - public void DataSizeFromKibiBytesShouldProduceTheExpectedConversionResults(double kibiBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromKibiBytes(kibiBytes); - - // Assert - Assert.Equal(kibiBytes, dataSize.KibiBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromMegaBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1000000)] - [InlineData(2, 2000000)] - [InlineData(3, 3000000)] - [InlineData(4, 4000000)] - [InlineData(5, 5000000)] - [InlineData(6, 6000000)] - [InlineData(7, 7000000)] - [InlineData(8, 8000000)] - [InlineData(9, 9000000)] - [InlineData(10, 10000000)] - public void DataSizeFromMegaBitsShouldProduceTheExpectedConversionResults(double megaBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromMegaBits(megaBits); - - // Assert - Assert.Equal(megaBits, dataSize.MegaBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromMebiBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1048576)] - [InlineData(2, 2097152)] - [InlineData(3, 3145728)] - [InlineData(4, 4194304)] - [InlineData(5, 5242880)] - [InlineData(6, 6291456)] - [InlineData(7, 7340032)] - [InlineData(8, 8388608)] - [InlineData(9, 9437184)] - [InlineData(10, 10485760)] - public void DataSizeFromMebiBitsShouldProduceTheExpectedConversionResults(double mebiBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromMebiBits(mebiBits); - - // Assert - Assert.Equal(mebiBits, dataSize.MebiBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromMegaBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8000000)] - [InlineData(2, 16000000)] - [InlineData(3, 24000000)] - [InlineData(4, 32000000)] - [InlineData(5, 40000000)] - [InlineData(6, 48000000)] - [InlineData(7, 56000000)] - [InlineData(8, 64000000)] - [InlineData(9, 72000000)] - [InlineData(10, 80000000)] - public void DataSizeFromMegaBytesShouldProduceTheExpectedConversionResults(double megaBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromMegaBytes(megaBytes); - - // Assert - Assert.Equal(megaBytes, dataSize.MegaBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromMebiBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8388608)] - [InlineData(2, 16777216)] - [InlineData(3, 25165824)] - [InlineData(4, 33554432)] - [InlineData(5, 41943040)] - [InlineData(6, 50331648)] - [InlineData(7, 58720256)] - [InlineData(8, 67108864)] - [InlineData(9, 75497472)] - [InlineData(10, 83886080)] - public void DataSizeFromMebiBytesShouldProduceTheExpectedConversionResults(double mebiBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromMebiBytes(mebiBytes); - - // Assert - Assert.Equal(mebiBytes, dataSize.MebiBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromGigaBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1000000000)] - [InlineData(2, 2000000000)] - [InlineData(3, 3000000000)] - [InlineData(4, 4000000000)] - [InlineData(5, 5000000000)] - [InlineData(6, 6000000000)] - [InlineData(7, 7000000000)] - [InlineData(8, 8000000000)] - [InlineData(9, 9000000000)] - [InlineData(10, 10000000000)] - public void DataSizeFromGigaBitsShouldProduceTheExpectedConversionResults(double gigaBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromGigaBits(gigaBits); - - // Assert - Assert.Equal(gigaBits, dataSize.GigaBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromGibiBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1073741824)] - [InlineData(2, 2147483648)] - [InlineData(3, 3221225472)] - [InlineData(4, 4294967296)] - [InlineData(5, 5368709120)] - [InlineData(6, 6442450944)] - [InlineData(7, 7516192768)] - [InlineData(8, 8589934592)] - [InlineData(9, 9663676416)] - [InlineData(10, 10737418240)] - public void DataSizeFromGibiBitsShouldProduceTheExpectedConversionResults(double gibiBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromGibiBits(gibiBits); - - // Assert - Assert.Equal(gibiBits, dataSize.GibiBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromGigaBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8000000000)] - [InlineData(2, 16000000000)] - [InlineData(3, 24000000000)] - [InlineData(4, 32000000000)] - [InlineData(5, 40000000000)] - [InlineData(6, 48000000000)] - [InlineData(7, 56000000000)] - [InlineData(8, 64000000000)] - [InlineData(9, 72000000000)] - [InlineData(10, 80000000000)] - public void DataSizeFromGigaBytesShouldProduceTheExpectedConversionResults(double gigaBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromGigaBytes(gigaBytes); - - // Assert - Assert.Equal(gigaBytes, dataSize.GigaBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromGibiBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8589934592)] - [InlineData(2, 17179869184)] - [InlineData(3, 25769803776)] - [InlineData(4, 34359738368)] - [InlineData(5, 42949672960)] - [InlineData(6, 51539607552)] - [InlineData(7, 60129542144)] - [InlineData(8, 68719476736)] - [InlineData(9, 77309411328)] - [InlineData(10, 85899345920)] - public void DataSizeFromGibiBytesShouldProduceTheExpectedConversionResults(double gibiBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromGibiBytes(gibiBytes); - - // Assert - Assert.Equal(gibiBytes, dataSize.GibiBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromTeraBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1000000000000)] - [InlineData(2, 2000000000000)] - [InlineData(3, 3000000000000)] - [InlineData(4, 4000000000000)] - [InlineData(5, 5000000000000)] - [InlineData(6, 6000000000000)] - [InlineData(7, 7000000000000)] - [InlineData(8, 8000000000000)] - [InlineData(9, 9000000000000)] - [InlineData(10, 10000000000000)] - public void DataSizeFromTeraBitsShouldProduceTheExpectedConversionResults(double teraBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromTeraBits(teraBits); - - // Assert - Assert.Equal(teraBits, dataSize.TeraBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromTebiBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1099511627776)] - [InlineData(2, 2199023255552)] - [InlineData(3, 3298534883328)] - [InlineData(4, 4398046511104)] - [InlineData(5, 5497558138880)] - [InlineData(6, 6597069766656)] - [InlineData(7, 7696581394432)] - [InlineData(8, 8796093022208)] - [InlineData(9, 9895604649984)] - [InlineData(10, 10995116277760)] - public void DataSizeFromTebiBitsShouldProduceTheExpectedConversionResults(double tebiBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromTebiBits(tebiBits); - - // Assert - Assert.Equal(tebiBits, dataSize.TebiBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromTeraBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8000000000000)] - [InlineData(2, 16000000000000)] - [InlineData(3, 24000000000000)] - [InlineData(4, 32000000000000)] - [InlineData(5, 40000000000000)] - [InlineData(6, 48000000000000)] - [InlineData(7, 56000000000000)] - [InlineData(8, 64000000000000)] - [InlineData(9, 72000000000000)] - [InlineData(10, 80000000000000)] - public void DataSizeFromTeraBytesShouldProduceTheExpectedConversionResults(double teraBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromTeraBytes(teraBytes); - - // Assert - Assert.Equal(teraBytes, dataSize.TeraBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromTebiBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8796093022208)] - [InlineData(2, 17592186044416)] - [InlineData(3, 26388279066624)] - [InlineData(4, 35184372088832)] - [InlineData(5, 43980465111040)] - [InlineData(6, 52776558133248)] - [InlineData(7, 61572651155456)] - [InlineData(8, 70368744177664)] - [InlineData(9, 79164837199872)] - [InlineData(10, 87960930222080)] - public void DataSizeFromTebiBytesShouldProduceTheExpectedConversionResults(double tebiBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromTebiBytes(tebiBytes); - - // Assert - Assert.Equal(tebiBytes, dataSize.TebiBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromPetaBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1000000000000000)] - [InlineData(2, 2000000000000000)] - [InlineData(3, 3000000000000000)] - [InlineData(4, 4000000000000000)] - [InlineData(5, 5000000000000000)] - [InlineData(6, 6000000000000000)] - [InlineData(7, 7000000000000000)] - [InlineData(8, 8000000000000000)] - [InlineData(9, 9000000000000000)] - [InlineData(10, 10000000000000000)] - public void DataSizeFromPetaBitsShouldProduceTheExpectedConversionResults(double petaBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromPetaBits(petaBits); - - // Assert - Assert.Equal(petaBits, dataSize.PetaBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromPebiBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1125899906842624)] - [InlineData(2, 2251799813685248)] - [InlineData(3, 3377699720527872)] - [InlineData(4, 4503599627370496)] - [InlineData(5, 5629499534213120)] - [InlineData(6, 6755399441055744)] - [InlineData(7, 7881299347898368)] - [InlineData(8, 9007199254740992)] - [InlineData(9, 10133099161583616)] - [InlineData(10, 11258999068426240)] - public void DataSizeFromPebiBitsShouldProduceTheExpectedConversionResults(double pebiBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromPebiBits(pebiBits); - - // Assert - Assert.Equal(pebiBits, dataSize.PebiBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromPetaBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8000000000000000)] - [InlineData(2, 16000000000000000)] - [InlineData(3, 24000000000000000)] - [InlineData(4, 32000000000000000)] - [InlineData(5, 40000000000000000)] - [InlineData(6, 48000000000000000)] - [InlineData(7, 56000000000000000)] - [InlineData(8, 64000000000000000)] - [InlineData(9, 72000000000000000)] - [InlineData(10, 80000000000000000)] - public void DataSizeFromPetaBytesShouldProduceTheExpectedConversionResults(double petaBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromPetaBytes(petaBytes); - - // Assert - Assert.Equal(petaBytes, dataSize.PetaBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromPebiBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 9007199254740992)] - [InlineData(2, 18014398509481984)] - [InlineData(3, 27021597764222976)] - [InlineData(4, 36028797018963970)] - [InlineData(5, 45035996273704960)] - [InlineData(6, 54043195528445950)] - [InlineData(7, 63050394783186940)] - [InlineData(8, 72057594037927940)] - [InlineData(9, 81064793292668930)] - [InlineData(10, 90071992547409920)] - public void DataSizeFromPebiBytesShouldProduceTheExpectedConversionResults(double pebiBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromPebiBytes(pebiBytes); - - // Assert - Assert.Equal(pebiBytes, dataSize.PebiBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromExaBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1E+18)] - [InlineData(2, 2E+18)] - [InlineData(3, 3E+18)] - [InlineData(4, 4E+18)] - [InlineData(5, 5E+18)] - [InlineData(6, 6E+18)] - [InlineData(7, 7E+18)] - [InlineData(8, 8E+18)] - [InlineData(9, 9E+18)] - [InlineData(10, 1E+19)] - public void DataSizeFromExaBitsShouldProduceTheExpectedConversionResults(double exaBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromExaBits(exaBits); - - // Assert - Assert.Equal(exaBits, dataSize.ExaBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromExbiBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1.152921504606847E+18)] - [InlineData(2, 2.305843009213694E+18)] - [InlineData(3, 3.458764513820541E+18)] - [InlineData(4, 4.611686018427388E+18)] - [InlineData(5, 5.764607523034235E+18)] - [InlineData(6, 6.917529027641082E+18)] - [InlineData(7, 8.070450532247929E+18)] - [InlineData(8, 9.223372036854776E+18)] - [InlineData(9, 1.0376293541461623E+19)] - [InlineData(10, 1.152921504606847E+19)] - public void DataSizeFromExbiBitsShouldProduceTheExpectedConversionResults(double exbiBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromExbiBits(exbiBits); - - // Assert - Assert.Equal(exbiBits, dataSize.ExbiBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromExaBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8E+18)] - [InlineData(2, 1.6E+19)] - [InlineData(3, 2.4E+19)] - [InlineData(4, 3.2E+19)] - [InlineData(5, 4E+19)] - [InlineData(6, 4.8E+19)] - [InlineData(7, 5.6E+19)] - [InlineData(8, 6.4E+19)] - [InlineData(9, 7.2E+19)] - [InlineData(10, 8E+19)] - public void DataSizeFromExaBytesShouldProduceTheExpectedConversionResults(double exaBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromExaBytes(exaBytes); - - // Assert - Assert.Equal(exaBytes, dataSize.ExaBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromExbiBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 9.223372036854776E+18)] - [InlineData(2, 1.8446744073709552E+19)] - [InlineData(3, 2.7670116110564327E+19)] - [InlineData(4, 3.6893488147419103E+19)] - [InlineData(5, 4.611686018427388E+19)] - [InlineData(6, 5.5340232221128655E+19)] - [InlineData(7, 6.456360425798343E+19)] - [InlineData(8, 7.378697629483821E+19)] - [InlineData(9, 8.301034833169298E+19)] - [InlineData(10, 9.223372036854776E+19)] - public void DataSizeFromExbiBytesShouldProduceTheExpectedConversionResults(double exbiBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromExbiBytes(exbiBytes); - - // Assert - Assert.Equal(exbiBytes, dataSize.ExbiBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromZettaBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1E+21)] - [InlineData(2, 2E+21)] - [InlineData(3, 3E+21)] - [InlineData(4, 4E+21)] - [InlineData(5, 5E+21)] - [InlineData(6, 6E+21)] - [InlineData(7, 7E+21)] - [InlineData(8, 8E+21)] - [InlineData(9, 9E+21)] - [InlineData(10, 1E+22)] - public void DataSizeFromZettaBitsShouldProduceTheExpectedConversionResults(double zettaBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromZettaBits(zettaBits); - - // Assert - Assert.Equal(zettaBits, dataSize.ZettaBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromZebiBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1.1805916207174113E+21)] - [InlineData(2, 2.3611832414348226E+21)] - [InlineData(3, 3.541774862152234E+21)] - [InlineData(4, 4.722366482869645E+21)] - [InlineData(5, 5.902958103587057E+21)] - [InlineData(6, 7.083549724304468E+21)] - [InlineData(7, 8.264141345021879E+21)] - [InlineData(8, 9.44473296573929E+21)] - [InlineData(9, 1.0625324586456702E+22)] - [InlineData(10, 1.1805916207174113E+22)] - public void DataSizeFromZebiBitsShouldProduceTheExpectedConversionResults(double zebiBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromZebiBits(zebiBits); - - // Assert - Assert.Equal(zebiBits, dataSize.ZebiBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromZettaBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8E+21)] - [InlineData(2, 1.6E+22)] - [InlineData(3, 2.4E+22)] - [InlineData(4, 3.2E+22)] - [InlineData(5, 4E+22)] - [InlineData(6, 4.8E+22)] - [InlineData(7, 5.6E+22)] - [InlineData(8, 6.4E+22)] - [InlineData(9, 7.2E+22)] - [InlineData(10, 8E+22)] - public void DataSizeFromZettaBytesShouldProduceTheExpectedConversionResults(double zettaBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromZettaBytes(zettaBytes); - - // Assert - Assert.Equal(zettaBytes, dataSize.ZettaBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromZebiBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 9.44473296573929E+21)] - [InlineData(2, 1.888946593147858E+22)] - [InlineData(3, 2.833419889721787E+22)] - [InlineData(4, 3.777893186295716E+22)] - [InlineData(5, 4.722366482869645E+22)] - [InlineData(6, 5.666839779443574E+22)] - [InlineData(7, 6.611313076017503E+22)] - [InlineData(8, 7.555786372591432E+22)] - [InlineData(9, 8.500259669165361E+22)] - [InlineData(10, 9.44473296573929E+22)] - public void DataSizeFromZebiBytesShouldProduceTheExpectedConversionResults(double zebiBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromZebiBytes(zebiBytes); - - // Assert - Assert.Equal(zebiBytes, dataSize.ZebiBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromYottaBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1E+24)] - [InlineData(2, 2E+24)] - [InlineData(3, 3E+24)] - [InlineData(4, 4E+24)] - [InlineData(4.999999999999999, 4.999999999999999E+24)] - [InlineData(6, 6E+24)] - [InlineData(7.000000000000001, 7E+24)] - [InlineData(8, 8E+24)] - [InlineData(9, 8.999999999999999E+24)] - [InlineData(9.999999999999998, 9.999999999999999E+24)] - public void DataSizeFromYottaBitsShouldProduceTheExpectedConversionResults(double yottaBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromYottaBits(yottaBits); - - // Assert - Assert.Equal(yottaBits, dataSize.YottaBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromYobiBits should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 1.2089258196146292E+24)] - [InlineData(2, 2.4178516392292583E+24)] - [InlineData(3, 3.6267774588438875E+24)] - [InlineData(4, 4.835703278458517E+24)] - [InlineData(5, 6.044629098073146E+24)] - [InlineData(6, 7.253554917687775E+24)] - [InlineData(7, 8.462480737302404E+24)] - [InlineData(8, 9.671406556917033E+24)] - [InlineData(9, 1.0880332376531663E+25)] - [InlineData(10, 1.2089258196146292E+25)] - public void DataSizeFromYobiBitsShouldProduceTheExpectedConversionResults(double yobiBits, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromYobiBits(yobiBits); - - // Assert - Assert.Equal(yobiBits, dataSize.YobiBits); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromYottaBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 8E+24)] - [InlineData(2, 1.6E+25)] - [InlineData(3, 2.4E+25)] - [InlineData(4, 3.2E+25)] - [InlineData(4.999999999999999, 3.9999999999999995E+25)] - [InlineData(6, 4.8E+25)] - [InlineData(7.000000000000001, 5.6E+25)] - [InlineData(8, 6.4E+25)] - [InlineData(9, 7.1999999999999994E+25)] - [InlineData(9.999999999999998, 7.999999999999999E+25)] - public void DataSizeFromYottaBytesShouldProduceTheExpectedConversionResults(double yottaBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromYottaBytes(yottaBytes); - - // Assert - Assert.Equal(yottaBytes, dataSize.YottaBytes); - Assert.Equal(bits, dataSize.Bits); - } - - [Theory(DisplayName = "DataSize.FromYobiBytes should produce the expected conversion results")] - [InlineData(0, 0)] - [InlineData(1, 9.671406556917033E+24)] - [InlineData(2, 1.9342813113834067E+25)] - [InlineData(3, 2.90142196707511E+25)] - [InlineData(4, 3.8685626227668134E+25)] - [InlineData(5, 4.835703278458517E+25)] - [InlineData(6, 5.80284393415022E+25)] - [InlineData(7, 6.769984589841923E+25)] - [InlineData(8, 7.737125245533627E+25)] - [InlineData(9, 8.70426590122533E+25)] - [InlineData(10, 9.671406556917033E+25)] - public void DataSizeFromYobiBytesShouldProduceTheExpectedConversionResults(double yobiBytes, double bits) - { - // Arrange / Act - DataSize dataSize = DataSize.FromYobiBytes(yobiBytes); - - // Assert - Assert.Equal(yobiBytes, dataSize.YobiBytes); - Assert.Equal(bits, dataSize.Bits); - } -} diff --git a/OnixLabs.Core.UnitTests/Units/TemperatureTests.cs b/OnixLabs.Core.UnitTests/Units/TemperatureTests.cs deleted file mode 100644 index 1548cd8..0000000 --- a/OnixLabs.Core.UnitTests/Units/TemperatureTests.cs +++ /dev/null @@ -1,470 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using OnixLabs.Core.Units; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Units; - -public sealed class TemperatureTests -{ - [Theory(DisplayName = "Temperature.FromKelvin should produce the expected conversion results")] - [InlineData(-1000, -1273.15, 2059.73, -2259.67, -420.14, -1018.52, -1800)] - [InlineData(-100, -373.15, 709.72, -639.67, -123.14, -298.52, -180)] - [InlineData(-90, -363.15, 694.72, -621.67, -119.84, -290.52, -162)] - [InlineData(-80, -353.15, 679.72, -603.67, -116.54, -282.52, -144)] - [InlineData(-70, -343.15, 664.72, -585.67, -113.24, -274.52, -126)] - [InlineData(-60, -333.15, 649.72, -567.67, -109.94, -266.52, -108)] - [InlineData(-50, -323.15, 634.72, -549.67, -106.64, -258.52, -90)] - [InlineData(-40, -313.15, 619.72, -531.67, -103.34, -250.52, -72)] - [InlineData(-30, -303.15, 604.72, -513.67, -100.04, -242.52, -54)] - [InlineData(-20, -293.15, 589.72, -495.67, -96.74, -234.52, -36)] - [InlineData(-10, -283.15, 574.72, -477.67, -93.44, -226.52, -18)] - [InlineData(-9, -282.15, 573.22, -475.87, -93.11, -225.72, -16.2)] - [InlineData(-8, -281.15, 571.72, -474.07, -92.78, -224.92, -14.4)] - [InlineData(-7, -280.15, 570.22, -472.27, -92.45, -224.12, -12.6)] - [InlineData(-6, -279.15, 568.72, -470.47, -92.12, -223.32, -10.8)] - [InlineData(-5, -278.15, 567.22, -468.67, -91.79, -222.52, -9)] - [InlineData(-4, -277.15, 565.72, -466.87, -91.46, -221.72, -7.2)] - [InlineData(-3, -276.15, 564.22, -465.07, -91.13, -220.92, -5.4)] - [InlineData(-2, -275.15, 562.72, -463.27, -90.8, -220.12, -3.6)] - [InlineData(-1, -274.15, 561.22, -461.47, -90.47, -219.32, -1.8)] - [InlineData(0, -273.15, 559.72, -459.67, -90.14, -218.52, 0)] - [InlineData(1, -272.15, 558.22, -457.87, -89.81, -217.72, 1.8)] - [InlineData(2, -271.15, 556.72, -456.07, -89.48, -216.92, 3.6)] - [InlineData(3, -270.15, 555.22, -454.27, -89.15, -216.12, 5.4)] - [InlineData(4, -269.15, 553.72, -452.47, -88.82, -215.32, 7.2)] - [InlineData(5, -268.15, 552.22, -450.67, -88.49, -214.52, 9)] - [InlineData(6, -267.15, 550.72, -448.87, -88.16, -213.72, 10.8)] - [InlineData(7, -266.15, 549.22, -447.07, -87.83, -212.92, 12.6)] - [InlineData(8, -265.15, 547.72, -445.27, -87.5, -212.12, 14.4)] - [InlineData(9, -264.15, 546.22, -443.47, -87.17, -211.32, 16.2)] - [InlineData(10, -263.15, 544.72, -441.67, -86.84, -210.52, 18)] - [InlineData(20, -253.15, 529.72, -423.67, -83.54, -202.52, 36)] - [InlineData(30, -243.15, 514.72, -405.67, -80.24, -194.52, 54)] - [InlineData(40, -233.15, 499.72, -387.67, -76.94, -186.52, 72)] - [InlineData(50, -223.15, 484.72, -369.67, -73.64, -178.52, 90)] - [InlineData(60, -213.15, 469.72, -351.67, -70.34, -170.52, 108)] - [InlineData(70, -203.15, 454.72, -333.67, -67.04, -162.52, 126)] - [InlineData(80, -193.15, 439.72, -315.67, -63.74, -154.52, 144)] - [InlineData(90, -183.15, 424.72, -297.67, -60.44, -146.52, 162)] - [InlineData(100, -173.15, 409.72, -279.67, -57.14, -138.52, 180)] - [InlineData(1000, 726.85, -940.28, 1340.33, 239.86, 581.48, 1800)] - public void TemperatureFromKelvinShouldProduceTheExpectedConversionResults( - double kelvin, - double celsius, - double delisle, - double fahrenheit, - double newton, - double reaumur, - double rankine) - { - // Arrange / Act - Temperature temperature = Temperature.FromKelvin(kelvin); - - // Assert - Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); - Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); - Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); - Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); - Assert.Equal(newton, Math.Round(temperature.Newton, 2)); - Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); - Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); - } - - [Theory(DisplayName = "Temperature.FromCelsius should produce the expected conversion results")] - [InlineData(-1000, -726.85, 1650, -1768, -330, -800, -1308.33)] - [InlineData(-100, 173.15, 300, -148, -33, -80, 311.67)] - [InlineData(-90, 183.15, 285, -130, -29.7, -72, 329.67)] - [InlineData(-80, 193.15, 270, -112, -26.4, -64, 347.67)] - [InlineData(-70, 203.15, 255, -94, -23.1, -56, 365.67)] - [InlineData(-60, 213.15, 240, -76, -19.8, -48, 383.67)] - [InlineData(-50, 223.15, 225, -58, -16.5, -40, 401.67)] - [InlineData(-40, 233.15, 210, -40, -13.2, -32, 419.67)] - [InlineData(-30, 243.15, 195, -22, -9.9, -24, 437.67)] - [InlineData(-20, 253.15, 180, -4, -6.6, -16, 455.67)] - [InlineData(-10, 263.15, 165, 14, -3.3, -8, 473.67)] - [InlineData(-9, 264.15, 163.5, 15.8, -2.97, -7.2, 475.47)] - [InlineData(-8, 265.15, 162, 17.6, -2.64, -6.4, 477.27)] - [InlineData(-7, 266.15, 160.5, 19.4, -2.31, -5.6, 479.07)] - [InlineData(-6, 267.15, 159, 21.2, -1.98, -4.8, 480.87)] - [InlineData(-5, 268.15, 157.5, 23, -1.65, -4, 482.67)] - [InlineData(-4, 269.15, 156, 24.8, -1.32, -3.2, 484.47)] - [InlineData(-3, 270.15, 154.5, 26.6, -0.99, -2.4, 486.27)] - [InlineData(-2, 271.15, 153, 28.4, -0.66, -1.6, 488.07)] - [InlineData(-1, 272.15, 151.5, 30.2, -0.33, -0.8, 489.87)] - [InlineData(0, 273.15, 150, 32, 0, 0, 491.67)] - [InlineData(1, 274.15, 148.5, 33.8, 0.33, 0.8, 493.47)] - [InlineData(2, 275.15, 147, 35.6, 0.66, 1.6, 495.27)] - [InlineData(3, 276.15, 145.5, 37.4, 0.99, 2.4, 497.07)] - [InlineData(4, 277.15, 144, 39.2, 1.32, 3.2, 498.87)] - [InlineData(5, 278.15, 142.5, 41, 1.65, 4, 500.67)] - [InlineData(6, 279.15, 141, 42.8, 1.98, 4.8, 502.47)] - [InlineData(7, 280.15, 139.5, 44.6, 2.31, 5.6, 504.27)] - [InlineData(8, 281.15, 138, 46.4, 2.64, 6.4, 506.07)] - [InlineData(9, 282.15, 136.5, 48.2, 2.97, 7.2, 507.87)] - [InlineData(10, 283.15, 135, 50, 3.3, 8, 509.67)] - [InlineData(20, 293.15, 120, 68, 6.6, 16, 527.67)] - [InlineData(30, 303.15, 105, 86, 9.9, 24, 545.67)] - [InlineData(40, 313.15, 90, 104, 13.2, 32, 563.67)] - [InlineData(50, 323.15, 75, 122, 16.5, 40, 581.67)] - [InlineData(60, 333.15, 60, 140, 19.8, 48, 599.67)] - [InlineData(70, 343.15, 45, 158, 23.1, 56, 617.67)] - [InlineData(80, 353.15, 30, 176, 26.4, 64, 635.67)] - [InlineData(90, 363.15, 15, 194, 29.7, 72, 653.67)] - [InlineData(100, 373.15, 0, 212, 33, 80, 671.67)] - [InlineData(1000, 1273.15, -1350, 1832, 330, 800, 2291.67)] - public void TemperatureFromCelsiusShouldProduceTheExpectedConversionResults( - double celsius, - double kelvin, - double delisle, - double fahrenheit, - double newton, - double reaumur, - double rankine) - { - // Arrange / Act - Temperature temperature = Temperature.FromCelsius(celsius); - - // Assert - Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); - Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); - Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); - Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); - Assert.Equal(newton, Math.Round(temperature.Newton, 2)); - Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); - Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); - } - - [Theory(DisplayName = "Temperature.FromDelisle should produce the expected conversion results")] - [InlineData(-1000, 1039.82, 766.67, 1412, 253, 613.33, 1871.67)] - [InlineData(-100, 439.82, 166.67, 332, 55, 133.33, 791.67)] - [InlineData(-90, 433.15, 160, 320, 52.8, 128, 779.67)] - [InlineData(-80, 426.48, 153.33, 308, 50.6, 122.67, 767.67)] - [InlineData(-70, 419.82, 146.67, 296, 48.4, 117.33, 755.67)] - [InlineData(-60, 413.15, 140, 284, 46.2, 112, 743.67)] - [InlineData(-50, 406.48, 133.33, 272, 44, 106.67, 731.67)] - [InlineData(-40, 399.82, 126.67, 260, 41.8, 101.33, 719.67)] - [InlineData(-30, 393.15, 120, 248, 39.6, 96, 707.67)] - [InlineData(-20, 386.48, 113.33, 236, 37.4, 90.67, 695.67)] - [InlineData(-10, 379.82, 106.67, 224, 35.2, 85.33, 683.67)] - [InlineData(-9, 379.15, 106, 222.8, 34.98, 84.8, 682.47)] - [InlineData(-8, 378.48, 105.33, 221.6, 34.76, 84.27, 681.27)] - [InlineData(-7, 377.82, 104.67, 220.4, 34.54, 83.73, 680.07)] - [InlineData(-6, 377.15, 104, 219.2, 34.32, 83.2, 678.87)] - [InlineData(-5, 376.48, 103.33, 218, 34.1, 82.67, 677.67)] - [InlineData(-4, 375.82, 102.67, 216.8, 33.88, 82.13, 676.47)] - [InlineData(-3, 375.15, 102, 215.6, 33.66, 81.6, 675.27)] - [InlineData(-2, 374.48, 101.33, 214.4, 33.44, 81.07, 674.07)] - [InlineData(-1, 373.82, 100.67, 213.2, 33.22, 80.53, 672.87)] - [InlineData(0, 373.15, 100, 212, 33, 80, 671.67)] - [InlineData(1, 372.48, 99.33, 210.8, 32.78, 79.47, 670.47)] - [InlineData(2, 371.82, 98.67, 209.6, 32.56, 78.93, 669.27)] - [InlineData(3, 371.15, 98, 208.4, 32.34, 78.4, 668.07)] - [InlineData(4, 370.48, 97.33, 207.2, 32.12, 77.87, 666.87)] - [InlineData(5, 369.82, 96.67, 206, 31.9, 77.33, 665.67)] - [InlineData(6, 369.15, 96, 204.8, 31.68, 76.8, 664.47)] - [InlineData(7, 368.48, 95.33, 203.6, 31.46, 76.27, 663.27)] - [InlineData(8, 367.82, 94.67, 202.4, 31.24, 75.73, 662.07)] - [InlineData(9, 367.15, 94, 201.2, 31.02, 75.2, 660.87)] - [InlineData(10, 366.48, 93.33, 200, 30.8, 74.67, 659.67)] - [InlineData(20, 359.82, 86.67, 188, 28.6, 69.33, 647.67)] - [InlineData(30, 353.15, 80, 176, 26.4, 64, 635.67)] - [InlineData(40, 346.48, 73.33, 164, 24.2, 58.67, 623.67)] - [InlineData(50, 339.82, 66.67, 152, 22, 53.33, 611.67)] - [InlineData(60, 333.15, 60, 140, 19.8, 48, 599.67)] - [InlineData(70, 326.48, 53.33, 128, 17.6, 42.67, 587.67)] - [InlineData(80, 319.82, 46.67, 116, 15.4, 37.33, 575.67)] - [InlineData(90, 313.15, 40, 104, 13.2, 32, 563.67)] - [InlineData(100, 306.48, 33.33, 92, 11, 26.67, 551.67)] - [InlineData(1000, -293.52, -566.67, -988, -187, -453.33, -528.33)] - public void TemperatureFromDelisleShouldProduceTheExpectedConversionResults( - double delisle, - double kelvin, - double celsius, - double fahrenheit, - double newton, - double reaumur, - double rankine) - { - // Arrange / Act - Temperature temperature = Temperature.FromDelisle(delisle); - - // Assert - Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); - Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); - Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); - Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); - Assert.Equal(newton, Math.Round(temperature.Newton, 2)); - Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); - Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); - } - - [Theory(DisplayName = "Temperature.FromFahrenheit should produce the expected conversion results")] - [InlineData(-1000, -300.18, -573.33, 1010, -189.2, -458.67, -540.33)] - [InlineData(-100, 199.82, -73.33, 260, -24.2, -58.67, 359.67)] - [InlineData(-90, 205.37, -67.78, 251.67, -22.37, -54.22, 369.67)] - [InlineData(-80, 210.93, -62.22, 243.33, -20.53, -49.78, 379.67)] - [InlineData(-70, 216.48, -56.67, 235, -18.7, -45.33, 389.67)] - [InlineData(-60, 222.04, -51.11, 226.67, -16.87, -40.89, 399.67)] - [InlineData(-50, 227.59, -45.56, 218.33, -15.03, -36.44, 409.67)] - [InlineData(-40, 233.15, -40, 210, -13.2, -32, 419.67)] - [InlineData(-30, 238.71, -34.44, 201.67, -11.37, -27.56, 429.67)] - [InlineData(-20, 244.26, -28.89, 193.33, -9.53, -23.11, 439.67)] - [InlineData(-10, 249.82, -23.33, 185, -7.7, -18.67, 449.67)] - [InlineData(-9, 250.37, -22.78, 184.17, -7.52, -18.22, 450.67)] - [InlineData(-8, 250.93, -22.22, 183.33, -7.33, -17.78, 451.67)] - [InlineData(-7, 251.48, -21.67, 182.5, -7.15, -17.33, 452.67)] - [InlineData(-6, 252.04, -21.11, 181.67, -6.97, -16.89, 453.67)] - [InlineData(-5, 252.59, -20.56, 180.83, -6.78, -16.44, 454.67)] - [InlineData(-4, 253.15, -20, 180, -6.6, -16, 455.67)] - [InlineData(-3, 253.71, -19.44, 179.17, -6.42, -15.56, 456.67)] - [InlineData(-2, 254.26, -18.89, 178.33, -6.23, -15.11, 457.67)] - [InlineData(-1, 254.82, -18.33, 177.5, -6.05, -14.67, 458.67)] - [InlineData(-0, 255.37, -17.78, 176.67, -5.87, -14.22, 459.67)] - [InlineData(1, 255.93, -17.22, 175.83, -5.68, -13.78, 460.67)] - [InlineData(2, 256.48, -16.67, 175, -5.5, -13.33, 461.67)] - [InlineData(3, 257.04, -16.11, 174.17, -5.32, -12.89, 462.67)] - [InlineData(4, 257.59, -15.56, 173.33, -5.13, -12.44, 463.67)] - [InlineData(5, 258.15, -15, 172.5, -4.95, -12, 464.67)] - [InlineData(6, 258.71, -14.44, 171.67, -4.77, -11.56, 465.67)] - [InlineData(7, 259.26, -13.89, 170.83, -4.58, -11.11, 466.67)] - [InlineData(8, 259.82, -13.33, 170, -4.4, -10.67, 467.67)] - [InlineData(9, 260.37, -12.78, 169.17, -4.22, -10.22, 468.67)] - [InlineData(10, 260.93, -12.22, 168.33, -4.03, -9.78, 469.67)] - [InlineData(20, 266.48, -6.67, 160, -2.2, -5.33, 479.67)] - [InlineData(30, 272.04, -1.11, 151.67, -0.37, -0.89, 489.67)] - [InlineData(40, 277.59, 4.44, 143.33, 1.47, 3.56, 499.67)] - [InlineData(50, 283.15, 10, 135, 3.3, 8, 509.67)] - [InlineData(60, 288.71, 15.56, 126.67, 5.13, 12.44, 519.67)] - [InlineData(70, 294.26, 21.11, 118.33, 6.97, 16.89, 529.67)] - [InlineData(80, 299.82, 26.67, 110, 8.8, 21.33, 539.67)] - [InlineData(90, 305.37, 32.22, 101.67, 10.63, 25.78, 549.67)] - [InlineData(100, 310.93, 37.78, 93.33, 12.47, 30.22, 559.67)] - [InlineData(1000, 810.93, 537.78, -656.67, 177.47, 430.22, 1459.67)] - public void TemperatureFromFahrenheitShouldProduceTheExpectedConversionResults( - double fahrenheit, - double kelvin, - double celsius, - double delisle, - double newton, - double reaumur, - double rankine) - { - // Arrange / Act - Temperature temperature = Temperature.FromFahrenheit(fahrenheit); - - // Assert - Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); - Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); - Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); - Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); - Assert.Equal(newton, Math.Round(temperature.Newton, 2)); - Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); - Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); - } - - [Theory(DisplayName = "Temperature.FromNewton should produce the expected conversion results")] - [InlineData(-1000, -2757.15, -3030.3, 4695.45, -5422.55, -2424.24, -4962.88)] - [InlineData(-100, -29.88, -303.03, 604.55, -513.45, -242.42, -53.78)] - [InlineData(-90, 0.42, -272.73, 559.09, -458.91, -218.18, 0.76)] - [InlineData(-80, 30.73, -242.42, 513.64, -404.36, -193.94, 55.31)] - [InlineData(-70, 61.03, -212.12, 468.18, -349.82, -169.7, 109.85)] - [InlineData(-60, 91.33, -181.82, 422.73, -295.27, -145.45, 164.4)] - [InlineData(-50, 121.63, -151.52, 377.27, -240.73, -121.21, 218.94)] - [InlineData(-40, 151.94, -121.21, 331.82, -186.18, -96.97, 273.49)] - [InlineData(-30, 182.24, -90.91, 286.36, -131.64, -72.73, 328.03)] - [InlineData(-20, 212.54, -60.61, 240.91, -77.09, -48.48, 382.58)] - [InlineData(-10, 242.85, -30.3, 195.45, -22.55, -24.24, 437.12)] - [InlineData(-9, 245.88, -27.27, 190.91, -17.09, -21.82, 442.58)] - [InlineData(-8, 248.91, -24.24, 186.36, -11.64, -19.39, 448.03)] - [InlineData(-7, 251.94, -21.21, 181.82, -6.18, -16.97, 453.49)] - [InlineData(-6, 254.97, -18.18, 177.27, -0.73, -14.55, 458.94)] - [InlineData(-5, 258, -15.15, 172.73, 4.73, -12.12, 464.4)] - [InlineData(-4, 261.03, -12.12, 168.18, 10.18, -9.7, 469.85)] - [InlineData(-3, 264.06, -9.09, 163.64, 15.64, -7.27, 475.31)] - [InlineData(-2, 267.09, -6.06, 159.09, 21.09, -4.85, 480.76)] - [InlineData(-1, 270.12, -3.03, 154.55, 26.55, -2.42, 486.22)] - [InlineData(0, 273.15, 0, 150, 32, 0, 491.67)] - [InlineData(1, 276.18, 3.03, 145.45, 37.45, 2.42, 497.12)] - [InlineData(2, 279.21, 6.06, 140.91, 42.91, 4.85, 502.58)] - [InlineData(3, 282.24, 9.09, 136.36, 48.36, 7.27, 508.03)] - [InlineData(4, 285.27, 12.12, 131.82, 53.82, 9.7, 513.49)] - [InlineData(5, 288.3, 15.15, 127.27, 59.27, 12.12, 518.94)] - [InlineData(6, 291.33, 18.18, 122.73, 64.73, 14.55, 524.4)] - [InlineData(7, 294.36, 21.21, 118.18, 70.18, 16.97, 529.85)] - [InlineData(8, 297.39, 24.24, 113.64, 75.64, 19.39, 535.31)] - [InlineData(9, 300.42, 27.27, 109.09, 81.09, 21.82, 540.76)] - [InlineData(10, 303.45, 30.3, 104.55, 86.55, 24.24, 546.22)] - [InlineData(20, 333.76, 60.61, 59.09, 141.09, 48.48, 600.76)] - [InlineData(30, 364.06, 90.91, 13.64, 195.64, 72.73, 655.31)] - [InlineData(40, 394.36, 121.21, -31.82, 250.18, 96.97, 709.85)] - [InlineData(50, 424.67, 151.52, -77.27, 304.73, 121.21, 764.4)] - [InlineData(60, 454.97, 181.82, -122.73, 359.27, 145.45, 818.94)] - [InlineData(70, 485.27, 212.12, -168.18, 413.82, 169.7, 873.49)] - [InlineData(80, 515.57, 242.42, -213.64, 468.36, 193.94, 928.03)] - [InlineData(90, 545.88, 272.73, -259.09, 522.91, 218.18, 982.58)] - [InlineData(100, 576.18, 303.03, -304.55, 577.45, 242.42, 1037.12)] - [InlineData(1000, 3303.45, 3030.3, -4395.45, 5486.55, 2424.24, 5946.22)] - public void TemperatureFromNewtonShouldProduceTheExpectedConversionResults( - double newton, - double kelvin, - double celsius, - double delisle, - double fahrenheit, - double reaumur, - double rankine) - { - // Arrange / Act - Temperature temperature = Temperature.FromNewton(newton); - - // Assert - Assert.Equal(newton, Math.Round(temperature.Newton, 2)); - Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); - Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); - Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); - Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); - Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); - Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); - } - - [Theory(DisplayName = "Temperature.FromReaumur should produce the expected conversion results")] - [InlineData(-1000, -976.85, -1250, 2025, -2218, -412.5, -1758.33)] - [InlineData(-100, 148.15, -125, 337.5, -193, -41.25, 266.67)] - [InlineData(-90, 160.65, -112.5, 318.75, -170.5, -37.12, 289.17)] - [InlineData(-80, 173.15, -100, 300, -148, -33, 311.67)] - [InlineData(-70, 185.65, -87.5, 281.25, -125.5, -28.88, 334.17)] - [InlineData(-60, 198.15, -75, 262.5, -103, -24.75, 356.67)] - [InlineData(-50, 210.65, -62.5, 243.75, -80.5, -20.62, 379.17)] - [InlineData(-40, 223.15, -50, 225, -58, -16.5, 401.67)] - [InlineData(-30, 235.65, -37.5, 206.25, -35.5, -12.38, 424.17)] - [InlineData(-20, 248.15, -25, 187.5, -13, -8.25, 446.67)] - [InlineData(-10, 260.65, -12.5, 168.75, 9.5, -4.12, 469.17)] - [InlineData(-9, 261.9, -11.25, 166.88, 11.75, -3.71, 471.42)] - [InlineData(-8, 263.15, -10, 165, 14, -3.3, 473.67)] - [InlineData(-7, 264.4, -8.75, 163.12, 16.25, -2.89, 475.92)] - [InlineData(-6, 265.65, -7.5, 161.25, 18.5, -2.48, 478.17)] - [InlineData(-5, 266.9, -6.25, 159.38, 20.75, -2.06, 480.42)] - [InlineData(-4, 268.15, -5, 157.5, 23, -1.65, 482.67)] - [InlineData(-3, 269.4, -3.75, 155.62, 25.25, -1.24, 484.92)] - [InlineData(-2, 270.65, -2.5, 153.75, 27.5, -0.82, 487.17)] - [InlineData(-1, 271.9, -1.25, 151.88, 29.75, -0.41, 489.42)] - [InlineData(0, 273.15, 0, 150, 32, 0, 491.67)] - [InlineData(1, 274.4, 1.25, 148.12, 34.25, 0.41, 493.92)] - [InlineData(2, 275.65, 2.5, 146.25, 36.5, 0.82, 496.17)] - [InlineData(3, 276.9, 3.75, 144.38, 38.75, 1.24, 498.42)] - [InlineData(4, 278.15, 5, 142.5, 41, 1.65, 500.67)] - [InlineData(5, 279.4, 6.25, 140.62, 43.25, 2.06, 502.92)] - [InlineData(6, 280.65, 7.5, 138.75, 45.5, 2.48, 505.17)] - [InlineData(7, 281.9, 8.75, 136.88, 47.75, 2.89, 507.42)] - [InlineData(8, 283.15, 10, 135, 50, 3.3, 509.67)] - [InlineData(9, 284.4, 11.25, 133.12, 52.25, 3.71, 511.92)] - [InlineData(10, 285.65, 12.5, 131.25, 54.5, 4.12, 514.17)] - [InlineData(20, 298.15, 25, 112.5, 77, 8.25, 536.67)] - [InlineData(30, 310.65, 37.5, 93.75, 99.5, 12.38, 559.17)] - [InlineData(40, 323.15, 50, 75, 122, 16.5, 581.67)] - [InlineData(50, 335.65, 62.5, 56.25, 144.5, 20.62, 604.17)] - [InlineData(60, 348.15, 75, 37.5, 167, 24.75, 626.67)] - [InlineData(70, 360.65, 87.5, 18.75, 189.5, 28.88, 649.17)] - [InlineData(80, 373.15, 100, 0, 212, 33, 671.67)] - [InlineData(90, 385.65, 112.5, -18.75, 234.5, 37.12, 694.17)] - [InlineData(100, 398.15, 125, -37.5, 257, 41.25, 716.67)] - [InlineData(1000, 1523.15, 1250, -1725, 2282, 412.5, 2741.67)] - public void TemperatureFromReaumurShouldProduceTheExpectedConversionResults( - double reaumur, - double kelvin, - double celsius, - double delisle, - double fahrenheit, - double newton, - double rankine) - { - // Arrange / Act - Temperature temperature = Temperature.FromReaumur(reaumur); - - // Assert - Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); - Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); - Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); - Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); - Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); - Assert.Equal(newton, Math.Round(temperature.Newton, 2)); - Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); - } - - [Theory(DisplayName = "Temperature.FromRankine should produce the expected conversion results")] - [InlineData(-1000, -555.56, -828.71, 1393.06, -1459.67, -273.47, -662.96)] - [InlineData(-100, -55.56, -328.71, 643.06, -559.67, -108.47, -262.96)] - [InlineData(-90, -50, -323.15, 634.72, -549.67, -106.64, -258.52)] - [InlineData(-80, -44.44, -317.59, 626.39, -539.67, -104.81, -254.08)] - [InlineData(-70, -38.89, -312.04, 618.06, -529.67, -102.97, -249.63)] - [InlineData(-60, -33.33, -306.48, 609.72, -519.67, -101.14, -245.19)] - [InlineData(-50, -27.78, -300.93, 601.39, -509.67, -99.31, -240.74)] - [InlineData(-40, -22.22, -295.37, 593.06, -499.67, -97.47, -236.3)] - [InlineData(-30, -16.67, -289.82, 584.72, -489.67, -95.64, -231.85)] - [InlineData(-20, -11.11, -284.26, 576.39, -479.67, -93.81, -227.41)] - [InlineData(-10, -5.56, -278.71, 568.06, -469.67, -91.97, -222.96)] - [InlineData(-9, -5, -278.15, 567.22, -468.67, -91.79, -222.52)] - [InlineData(-8, -4.44, -277.59, 566.39, -467.67, -91.61, -222.08)] - [InlineData(-7, -3.89, -277.04, 565.56, -466.67, -91.42, -221.63)] - [InlineData(-6, -3.33, -276.48, 564.72, -465.67, -91.24, -221.19)] - [InlineData(-5, -2.78, -275.93, 563.89, -464.67, -91.06, -220.74)] - [InlineData(-4, -2.22, -275.37, 563.06, -463.67, -90.87, -220.3)] - [InlineData(-3, -1.67, -274.82, 562.22, -462.67, -90.69, -219.85)] - [InlineData(-2, -1.11, -274.26, 561.39, -461.67, -90.51, -219.41)] - [InlineData(-1, -0.56, -273.71, 560.56, -460.67, -90.32, -218.96)] - [InlineData(0, 0, -273.15, 559.72, -459.67, -90.14, -218.52)] - [InlineData(1, 0.56, -272.59, 558.89, -458.67, -89.96, -218.08)] - [InlineData(2, 1.11, -272.04, 558.06, -457.67, -89.77, -217.63)] - [InlineData(3, 1.67, -271.48, 557.22, -456.67, -89.59, -217.19)] - [InlineData(4, 2.22, -270.93, 556.39, -455.67, -89.41, -216.74)] - [InlineData(5, 2.78, -270.37, 555.56, -454.67, -89.22, -216.3)] - [InlineData(6, 3.33, -269.82, 554.72, -453.67, -89.04, -215.85)] - [InlineData(7, 3.89, -269.26, 553.89, -452.67, -88.86, -215.41)] - [InlineData(8, 4.44, -268.71, 553.06, -451.67, -88.67, -214.96)] - [InlineData(9, 5, -268.15, 552.22, -450.67, -88.49, -214.52)] - [InlineData(10, 5.56, -267.59, 551.39, -449.67, -88.31, -214.08)] - [InlineData(20, 11.11, -262.04, 543.06, -439.67, -86.47, -209.63)] - [InlineData(30, 16.67, -256.48, 534.72, -429.67, -84.64, -205.19)] - [InlineData(40, 22.22, -250.93, 526.39, -419.67, -82.81, -200.74)] - [InlineData(50, 27.78, -245.37, 518.06, -409.67, -80.97, -196.3)] - [InlineData(60, 33.33, -239.82, 509.72, -399.67, -79.14, -191.85)] - [InlineData(70, 38.89, -234.26, 501.39, -389.67, -77.31, -187.41)] - [InlineData(80, 44.44, -228.71, 493.06, -379.67, -75.47, -182.96)] - [InlineData(90, 50, -223.15, 484.72, -369.67, -73.64, -178.52)] - [InlineData(100, 55.56, -217.59, 476.39, -359.67, -71.81, -174.08)] - [InlineData(1000, 555.56, 282.41, -273.61, 540.33, 93.19, 225.92)] - public void TemperatureFromRankineShouldProduceTheExpectedConversionResults( - double rankine, - double kelvin, - double celsius, - double delisle, - double fahrenheit, - double newton, - double reaumur) - { - // Arrange / Act - Temperature temperature = Temperature.FromRankine(rankine); - - // Assert - Assert.Equal(rankine, Math.Round(temperature.Rankine, 2)); - Assert.Equal(kelvin, Math.Round(temperature.Kelvin, 2)); - Assert.Equal(celsius, Math.Round(temperature.Celsius, 2)); - Assert.Equal(delisle, Math.Round(temperature.Delisle, 2)); - Assert.Equal(fahrenheit, Math.Round(temperature.Fahrenheit, 2)); - Assert.Equal(newton, Math.Round(temperature.Newton, 2)); - Assert.Equal(reaumur, Math.Round(temperature.Reaumur, 2)); - } -} diff --git a/OnixLabs.Core/Collections/Collection.Empty.cs b/OnixLabs.Core/Collections/Collection.Empty.cs index 50cacb4..8bc0146 100644 --- a/OnixLabs.Core/Collections/Collection.Empty.cs +++ b/OnixLabs.Core/Collections/Collection.Empty.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,7 +16,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Runtime.CompilerServices; namespace OnixLabs.Core.Collections; @@ -30,7 +29,6 @@ public static partial class Collection /// /// The underlying type of the enumerable. /// Returns an empty enumerable. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static IEnumerable EmptyEnumerable() { return Enumerable.Empty(); @@ -41,7 +39,6 @@ public static IEnumerable EmptyEnumerable() /// /// The underlying type of the array. /// Returns an empty array. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static T[] EmptyArray() { return Array.Empty(); @@ -52,7 +49,6 @@ public static T[] EmptyArray() /// /// The underlying type of the immutable array. /// Returns an empty immutable array. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableArray EmptyImmutableArray() { return ImmutableArray.Empty; @@ -63,7 +59,6 @@ public static ImmutableArray EmptyImmutableArray() /// /// The underlying type of the list. /// Returns an empty list. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static List EmptyList() { return []; @@ -74,7 +69,6 @@ public static List EmptyList() /// /// The underlying type of the immutable list. /// Returns an empty immutable list. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableList EmptyImmutableList() { return ImmutableList.Empty; @@ -86,7 +80,6 @@ public static ImmutableList EmptyImmutableList() /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns an empty dictionary. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Dictionary EmptyDictionary() where TKey : notnull { return []; @@ -98,7 +91,6 @@ public static Dictionary EmptyDictionary() where TKe /// The underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an empty immutable dictionary. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableDictionary EmptyImmutableDictionary() where TKey : notnull { return ImmutableDictionary.Empty; @@ -110,7 +102,6 @@ public static ImmutableDictionary EmptyImmutableDictionaryThe underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns an empty sorted dictionary. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedDictionary EmptySortedDictionary() where TKey : notnull { return []; @@ -122,7 +113,6 @@ public static SortedDictionary EmptySortedDictionary /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an empty immutable sorted dictionary. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedDictionary EmptyImmutableSortedDictionary() where TKey : notnull { return ImmutableSortedDictionary.Empty; @@ -133,7 +123,6 @@ public static ImmutableSortedDictionary EmptyImmutableSortedDictio /// /// The underlying type of the hash set. /// Returns an empty hash set. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static HashSet EmptyHashSet() { return []; @@ -144,7 +133,6 @@ public static HashSet EmptyHashSet() /// /// The underlying type of the immutable hash set. /// Returns an empty immutable hash set. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableHashSet EmptyImmutableHashSet() { return ImmutableHashSet.Empty; @@ -155,7 +143,6 @@ public static ImmutableHashSet EmptyImmutableHashSet() /// /// The underlying type of the sorted set. /// Returns an empty sorted set. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedSet EmptySortedSet() { return []; @@ -166,7 +153,6 @@ public static SortedSet EmptySortedSet() /// /// The underlying type of the immutable sorted set. /// Returns an empty immutable sorted set. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedSet EmptyImmutableSortedSet() { return ImmutableSortedSet.Empty; @@ -177,7 +163,6 @@ public static ImmutableSortedSet EmptyImmutableSortedSet() /// /// The underlying type of the stack. /// Returns an empty stack. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Stack EmptyStack() { return []; @@ -188,7 +173,6 @@ public static Stack EmptyStack() /// /// The underlying type of the immutable stack. /// Returns an empty immutable stack. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableStack EmptyImmutableStack() { return ImmutableStack.Empty; @@ -199,7 +183,6 @@ public static ImmutableStack EmptyImmutableStack() /// /// The underlying type of the queue. /// Returns an empty queue. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Queue EmptyQueue() { return []; @@ -210,7 +193,6 @@ public static Queue EmptyQueue() /// /// The underlying type of the immutable queue. /// Returns an empty immutable queue. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableQueue EmptyImmutableQueue() { return ImmutableQueue.Empty; diff --git a/OnixLabs.Core/Collections/Collection.Of.cs b/OnixLabs.Core/Collections/Collection.Of.cs index 624a841..1d35a57 100644 --- a/OnixLabs.Core/Collections/Collection.Of.cs +++ b/OnixLabs.Core/Collections/Collection.Of.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,7 +15,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Runtime.CompilerServices; namespace OnixLabs.Core.Collections; @@ -27,7 +26,6 @@ public static partial class Collection /// The items which will populate the enumerable. /// The underlying type of the enumerable. /// Returns an enumerable populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static IEnumerable EnumerableOf(params T[] items) { return [..items]; @@ -39,7 +37,6 @@ public static IEnumerable EnumerableOf(params T[] items) /// The items which will populate the array. /// The underlying type of the array. /// Returns an array populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static T[] ArrayOf(params T[] items) { return [..items]; @@ -51,7 +48,6 @@ public static T[] ArrayOf(params T[] items) /// The items which will populate the immutable array. /// The underlying type of the immutable array. /// Returns an immutable array populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableArray ImmutableArrayOf(params T[] items) { return [..items]; @@ -63,7 +59,6 @@ public static ImmutableArray ImmutableArrayOf(params T[] items) /// The items which will populate the list. /// The underlying type of the list. /// Returns a list populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static List ListOf(params T[] items) { return [..items]; @@ -75,7 +70,6 @@ public static List ListOf(params T[] items) /// The items which will populate the immutable list. /// The underlying type of the immutable list. /// Returns an immutable list populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableList ImmutableListOf(params T[] items) { return [..items]; @@ -88,7 +82,6 @@ public static ImmutableList ImmutableListOf(params T[] items) /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns a dictionary populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Dictionary DictionaryOf(params KeyValuePair[] items) where TKey : notnull { return new Dictionary(items); @@ -101,7 +94,6 @@ public static Dictionary DictionaryOf(params KeyValu /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns a dictionary populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Dictionary DictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull { return DictionaryOf(items.Select(item => new KeyValuePair(item.key, item.value)).ToArray()); @@ -114,7 +106,6 @@ public static Dictionary DictionaryOf(params (TKey k /// The underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an immutable dictionary populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableDictionary ImmutableDictionaryOf( params KeyValuePair[] items) where TKey : notnull { @@ -128,7 +119,6 @@ public static ImmutableDictionary ImmutableDictionaryOfThe underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an immutable dictionary populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableDictionary ImmutableDictionaryOf( params (TKey key, TValue value)[] items) where TKey : notnull { @@ -142,7 +132,6 @@ public static ImmutableDictionary ImmutableDictionaryOfThe underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns a sorted dictionary populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedDictionary SortedDictionaryOf( params KeyValuePair[] items) where TKey : notnull { @@ -156,7 +145,6 @@ public static SortedDictionary SortedDictionaryOf( /// The underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns a sorted dictionary populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedDictionary SortedDictionaryOf( params (TKey key, TValue value)[] items) where TKey : notnull { @@ -170,7 +158,6 @@ public static SortedDictionary SortedDictionaryOf( /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an immutable sorted dictionary populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( params KeyValuePair[] items) where TKey : notnull { @@ -184,7 +171,6 @@ public static ImmutableSortedDictionary ImmutableSortedDictionaryO /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an immutable sorted dictionary populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( params (TKey key, TValue value)[] items) where TKey : notnull { @@ -197,7 +183,6 @@ public static ImmutableSortedDictionary ImmutableSortedDictionaryO /// The items which will populate the hash set. /// The underlying type of the hash set. /// Returns a hash set populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static HashSet HashSetOf(params T[] items) { return [..items]; @@ -209,7 +194,6 @@ public static HashSet HashSetOf(params T[] items) /// The items which will populate the immutable hash set. /// The underlying type of the immutable hash set. /// Returns an immutable hash set populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableHashSet ImmutableHashSetOf(params T[] items) { return [..items]; @@ -221,7 +205,6 @@ public static ImmutableHashSet ImmutableHashSetOf(params T[] items) /// The items which will populate the sorted set. /// The underlying type of the sorted set. /// Returns a sorted set populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static SortedSet SortedSetOf(params T[] items) { return [..items]; @@ -233,7 +216,6 @@ public static SortedSet SortedSetOf(params T[] items) /// The items which will populate the immutable sorted set. /// The underlying type of the immutable sorted set. /// Returns an immutable sorted set populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) { return [..items]; @@ -245,7 +227,6 @@ public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) /// The items which will populate the stack. /// The underlying type of the stack. /// Returns a stack populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Stack StackOf(params T[] items) { return new Stack(items); @@ -257,7 +238,6 @@ public static Stack StackOf(params T[] items) /// The items which will populate the immutable stack. /// The underlying type of the immutable stack. /// Returns an immutable stack populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableStack ImmutableStackOf(params T[] items) { return [..items]; @@ -269,7 +249,6 @@ public static ImmutableStack ImmutableStackOf(params T[] items) /// The items which will populate the queue. /// The underlying type of the queue. /// Returns a queue populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static Queue QueueOf(params T[] items) { return new Queue(items); @@ -281,7 +260,6 @@ public static Queue QueueOf(params T[] items) /// The items which will populate the immutable queue. /// The underlying type of the immutable queue. /// Returns an immutable queue populated with the specified items. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static ImmutableQueue ImmutableQueueOf(params T[] items) { return [..items]; diff --git a/OnixLabs.Core/Extensions.Object.cs b/OnixLabs.Core/Extensions.Object.cs index 67214fb..49a30d2 100644 --- a/OnixLabs.Core/Extensions.Object.cs +++ b/OnixLabs.Core/Extensions.Object.cs @@ -32,7 +32,7 @@ public static class ObjectExtensions /// The current to compare to the specified object. /// The to compare to the current . /// The underlying type of the current . - /// Returns a value that indicates the relative order of the objects being compared. + /// Returns a signed integer that indicates the relative order of the objects being compared. /// If the specified object is not null, or of the specified type. public static int CompareObject(this IComparable comparable, object? obj) { diff --git a/OnixLabs.Core/Extensions.String.cs b/OnixLabs.Core/Extensions.String.cs index 387de23..d3c193a 100644 --- a/OnixLabs.Core/Extensions.String.cs +++ b/OnixLabs.Core/Extensions.String.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -71,11 +71,7 @@ public static string SubstringBeforeFirst(this string value, char delimiter, str /// The value to return if the delimiter is not found, which defaults to the original string. /// Specifies the string comparison rule for the search. /// Returns a substring before the first occurrence of the specified delimiter. - public static string SubstringBeforeFirst( - this string value, - string delimiter, - string? defaultValue = null, - StringComparison comparison = StringComparison.Ordinal) + public static string SubstringBeforeFirst(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = StringComparison.Ordinal) { int index = value.IndexOf(delimiter, comparison); @@ -112,11 +108,7 @@ public static string SubstringBeforeLast(this string value, char delimiter, stri /// The value to return if the delimiter is not found, which defaults to the original string. /// Specifies the string comparison rule for the search. /// Returns a substring before the last occurrence of the specified delimiter. - public static string SubstringBeforeLast( - this string value, - string delimiter, - string? defaultValue = null, - StringComparison comparison = StringComparison.Ordinal) + public static string SubstringBeforeLast(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = StringComparison.Ordinal) { int index = value.LastIndexOf(delimiter, comparison); @@ -153,11 +145,7 @@ public static string SubstringAfterFirst(this string value, char delimiter, stri /// The value to return if the delimiter is not found, which defaults to the original string. /// Specifies the string comparison rule for the search. /// Returns a substring after the first occurrence of the specified delimiter. - public static string SubstringAfterFirst( - this string value, - string delimiter, - string? defaultValue = null, - StringComparison comparison = StringComparison.Ordinal) + public static string SubstringAfterFirst(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = StringComparison.Ordinal) { int index = value.IndexOf(delimiter, comparison); @@ -194,11 +182,7 @@ public static string SubstringAfterLast(this string value, char delimiter, strin /// The value to return if the delimiter is not found, which defaults to the original string. /// Specifies the string comparison rule for the search. /// Returns a substring after the last occurrence of the specified delimiter. - public static string SubstringAfterLast( - this string value, - string delimiter, - string? defaultValue = null, - StringComparison comparison = StringComparison.Ordinal) + public static string SubstringAfterLast(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = StringComparison.Ordinal) { int index = value.LastIndexOf(delimiter, comparison); @@ -266,6 +250,18 @@ public static TimeOnly ToTimeOnly(this string value, IFormatProvider? provider = return TimeOnly.Parse(value, provider, styles); } + /// + /// Converts the current between the specified before and after values. + /// + /// The current value to wrap. + /// The that should precede the current value. + /// The that should succeed the current value. + /// Returns the current wrapped between the specified before and after values. + public static string Wrap(this string value, char before, char after) + { + return $"{before}{value}{after}"; + } + /// /// Converts the current between the specified before and after values. /// diff --git a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs index 540ef8d..9786d4c 100644 --- a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs +++ b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -243,4 +243,28 @@ public static IEnumerable WhereNotNull(this IEnumerable enumerable) { return enumerable.Where(element => element is not null)!; } + + /// + /// Formats the current as a collection string. + /// + /// The to format. + /// The underlying type of the . + /// Returns a collection representation of the current . + public static string ToCollectionString(this IEnumerable enumerable) + { + return string.Join(", ", enumerable).Wrap('[', ']'); + } + + /// + /// Formats each element of the current current as a collection string. + /// + /// The to format. + /// The format which will be applied to each element. + /// The provider to use to format the value. + /// The underlying type of the . + /// Returns a collection representation of the current . + public static string ToCollectionString(this IEnumerable enumerable, string format, IFormatProvider? formatProvider = null) where T : IFormattable + { + return enumerable.Select(element => element.ToString(format, formatProvider)).ToCollectionString(); + } } diff --git a/OnixLabs.Core/Numerics/GenericMath.cs b/OnixLabs.Core/Numerics/GenericMath.cs deleted file mode 100644 index c9f5e1d..0000000 --- a/OnixLabs.Core/Numerics/GenericMath.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.Numerics; - -/// -/// Provides generic mathematical functions. -/// -internal static class GenericMath -{ - /// - /// Calculates the power of the specified value, raised by the specified exponent. - /// - /// The value to raise to the power of the specified exponent. - /// The specified exponent to raise the value by. - /// The underlying type. - /// Returns the power of the specified value, raised by the specified exponent. - public static T Pow(T value, int exponent) where T : INumber - { - if (exponent == 0) return T.One; - if (exponent == 1 || value == T.One) return value; - - T result = value; - int count = int.Abs(exponent); - - while (--count > 0) result *= value; - - return exponent > 1 ? result : T.One / result; - } -} diff --git a/OnixLabs.Core/Preconditions.cs b/OnixLabs.Core/Preconditions.cs index b255ee0..4811d45 100644 --- a/OnixLabs.Core/Preconditions.cs +++ b/OnixLabs.Core/Preconditions.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,6 +14,7 @@ using System; using System.Runtime.CompilerServices; +using OnixLabs.Core.Linq; namespace OnixLabs.Core; @@ -28,7 +29,6 @@ public static class Preconditions /// The condition to check. /// The exception message to throw in the event that the condition fails. /// If the condition fails. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static void Check(bool condition, string message = "Check requirement failed.") { if (!condition) throw new InvalidOperationException(message); @@ -42,7 +42,6 @@ public static void Check(bool condition, string message = "Check requirement fai /// The underlying type of the value. /// Returns the specified value as non-nullable in the event that the value is not null. /// If the condition fails because the value is null. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static T CheckNotNull(T? value, string message = "Argument must not be null.") where T : notnull { return value ?? throw new InvalidOperationException(message); @@ -55,7 +54,6 @@ public static T CheckNotNull(T? value, string message = "Argument must not be /// The exception message to throw in the event that the condition fails. /// The name of the parameter which is invalid. /// If the condition fails. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static void Require(bool condition, string message = "Argument requirement failed.", string? parameterName = null) { if (!condition) throw new ArgumentException(message, parameterName); @@ -70,10 +68,25 @@ public static void Require(bool condition, string message = "Argument requiremen /// The underlying type of the value. /// Returns the specified value as non-nullable in the event that the value is not null. /// If the condition fails because the value is null. - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] public static T RequireNotNull(T? value, string message = "Argument must not be null.", string? parameterName = null) where T : notnull { return value ?? throw new ArgumentNullException(parameterName, message); } + + /// + /// Performs a pre-condition requirement that the specified enum value is defined in the enum. + /// + /// The enum value to check. + /// The name of the parameter being checked. + /// The underlying type of the enum value. + /// Returns the specified enum value if it is defined in the enum. + /// If the specified value does not exist in the enum. + public static void RequireIsDefined(T value, string? parameterName = null) where T : struct, Enum + { + if (Enum.IsDefined(value)) return; + + string message = $"Invalid {typeof(T).Name} enum value: {value}. Valid values include: {Enum.GetNames().JoinToString()}."; + throw new ArgumentOutOfRangeException(parameterName, message); + } } diff --git a/OnixLabs.Core/Text/StringBuilderExtensions.cs b/OnixLabs.Core/Text/StringBuilderExtensions.cs new file mode 100644 index 0000000..e644d05 --- /dev/null +++ b/OnixLabs.Core/Text/StringBuilderExtensions.cs @@ -0,0 +1,151 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.ComponentModel; +using System.Text; +using OnixLabs.Core.Linq; + +namespace OnixLabs.Core.Text; + +/// +/// Provides extension methods for string builders. +/// +// ReSharper disable UnusedMethodReturnValue.Global +[EditorBrowsable(EditorBrowsableState.Never)] +public static class StringBuilderExtensions +{ + /// + /// Appends the specified values to the current . + /// + /// The to append to. + /// The values to append. + /// Returns the current with the specified items appended. + public static StringBuilder Append(this StringBuilder builder, params object[] values) + { + return builder.Append(values.JoinToString(string.Empty)); + } + + /// + /// Prepends the specified values to the current . + /// + /// The to prepend to. + /// The values to prepend. + /// Returns the current with the specified items prepended. + public static StringBuilder Prepend(this StringBuilder builder, params object[] values) + { + return builder.Insert(0, values.JoinToString(string.Empty)); + } + + /// + /// Trims the specified value from the start and end of the current . + /// + /// The to trim. + /// The value to trim. + /// Returns the current with the specified value trimmed from the start and end. + public static StringBuilder Trim(this StringBuilder builder, char value) + { + return builder.TrimStart(value).TrimEnd(value); + } + + /// + /// Trims the specified value from the end of the current . + /// + /// The to trim. + /// The value to trim. + /// Returns the current with the specified value trimmed from the end. + public static StringBuilder TrimEnd(this StringBuilder builder, char value) + { + while (builder.Length > 0 && builder[^1] == value) + builder.Remove(builder.Length - 1, 1); + + return builder; + } + + /// + /// Trims the specified value from the start of the current . + /// + /// The to trim. + /// The value to trim. + /// Returns the current with the specified value trimmed from the start. + public static StringBuilder TrimStart(this StringBuilder builder, char value) + { + while (builder.Length > 0 && builder[0] == value) + builder.Remove(0, 1); + + return builder; + } + + /// + /// Trims the specified value from the start and end of the current . + /// + /// The to trim. + /// The value to trim. + /// Returns the current with the specified value trimmed from the start and end. + public static StringBuilder Trim(this StringBuilder builder, string value) + { + return builder.TrimStart(value).TrimEnd(value); + } + + /// + /// Trims the specified value from the end of the current . + /// + /// The to trim. + /// The value to trim. + /// Returns the current with the specified value trimmed from the end. + public static StringBuilder TrimEnd(this StringBuilder builder, string value) + { + while (builder.Length >= value.Length && builder.ToString(builder.Length - value.Length, value.Length) == value) + builder.Remove(builder.Length - value.Length, value.Length); + + return builder; + } + + /// + /// Trims the specified value from the start of the current . + /// + /// The to trim. + /// The value to trim. + /// Returns the current with the specified value trimmed from the start. + public static StringBuilder TrimStart(this StringBuilder builder, string value) + { + while (builder.Length >= value.Length && builder.ToString(0, value.Length) == value) + builder.Remove(0, value.Length); + + return builder; + } + + /// + /// Wraps the current between the specified start and end values. + /// + /// The to wrap. + /// The value to prepend. + /// The value to append. + /// Returns the current wrapped between the specified start and end values. + public static StringBuilder Wrap(this StringBuilder builder, char start, char end) + { + return builder.Prepend(start).Append(end); + } + + /// + /// Wraps the current between the specified start and end values. + /// + /// The to wrap. + /// The value to prepend. + /// The value to append. + /// Returns the current wrapped between the specified start and end values. + public static StringBuilder Wrap(this StringBuilder builder, string start, string end) + { + return builder.Prepend(start).Append(end); + } +} diff --git a/OnixLabs.Core/Units/DataSize.Arithmetic.cs b/OnixLabs.Core/Units/DataSize.Arithmetic.cs deleted file mode 100644 index 099b604..0000000 --- a/OnixLabs.Core/Units/DataSize.Arithmetic.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Core.Units; - -public readonly partial struct DataSize -{ - /// - /// Computes the sum of the specified values. - /// - /// The left-hand value to add to. - /// The right-hand value to add. - /// Returns the sum of the specified values. - public static DataSize Add(DataSize left, DataSize right) - { - return new DataSize(left.Bits + right.Bits); - } - - /// - /// Computes the difference between the specified values. - /// - /// The left-hand value to subtract from. - /// The right-hand value to subtract. - /// Returns the difference between the specified values. - public static DataSize Subtract(DataSize left, DataSize right) - { - return new DataSize(left.Bits - right.Bits); - } - - /// - /// Computes the product of the specified values. - /// - /// The left-hand value to multiply. - /// The right-hand value to multiply by. - /// Returns the product of the specified values. - public static DataSize Multiply(DataSize left, DataSize right) - { - return new DataSize(left.Bits * right.Bits); - } - - /// - /// Computes the quotient of the specified values. - /// - /// The left-hand value to divide. - /// The right-hand value to divide by. - /// Returns the quotient of the specified values. - public static DataSize Divide(DataSize left, DataSize right) - { - return new DataSize(left.Bits / right.Bits); - } - - /// - /// Computes the sum of the specified values. - /// - /// The left-hand value to add to. - /// The right-hand value to add. - /// Returns the sum of the specified values. - public static DataSize operator +(DataSize left, DataSize right) - { - return Add(left, right); - } - - /// - /// Computes the difference between the specified values. - /// - /// The left-hand value to subtract from. - /// The right-hand value to subtract. - /// Returns the difference between the specified values. - public static DataSize operator -(DataSize left, DataSize right) - { - return Subtract(left, right); - } - - /// - /// Computes the product of the specified values. - /// - /// The left-hand value to multiply. - /// The right-hand value to multiply by. - /// Returns the product of the specified values. - public static DataSize operator *(DataSize left, DataSize right) - { - return Multiply(left, right); - } - - /// - /// Computes the quotient of the specified values. - /// - /// The left-hand value to divide. - /// The right-hand value to divide by. - /// Returns the quotient of the specified values. - public static DataSize operator /(DataSize left, DataSize right) - { - return Divide(left, right); - } -} diff --git a/OnixLabs.Core/Units/DataSize.Constants.cs b/OnixLabs.Core/Units/DataSize.Constants.cs deleted file mode 100644 index cb14099..0000000 --- a/OnixLabs.Core/Units/DataSize.Constants.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Core.Units; - -public readonly partial struct DataSize -{ - /// - /// Represents a zero-bit value. - /// - public static DataSize Zero => default; - - /// - /// Gets the number of bits per nibble. - /// - private static T BitsPerNibble => T.CreateChecked(4); - - /// - /// Gets the number of bits per byte. - /// - private static T BitsPerByte => T.CreateChecked(8); - - /// - /// Gets the number of bits per word. - /// - private static T BitsPerWord => T.CreateChecked(16); - - /// - /// Gets the number of bits per double-word. - /// - private static T BitsPerDoubleWord => T.CreateChecked(32); - - /// - /// Gets the number of bits per quad-word. - /// - private static T BitsPerQuadWord => T.CreateChecked(64); - - /// - /// Gets the value of a binary thousand. - /// - private static T BinaryThousand => T.CreateChecked(1024); - - /// - /// Gets the value of a decimal thousand. - /// - private static T DecimalThousand => T.CreateChecked(1000); - - /// - /// Gets the default format. - /// - private const string DefaultFormat = "b"; -} diff --git a/OnixLabs.Core/Units/DataSize.Equatable.cs b/OnixLabs.Core/Units/DataSize.Equatable.cs deleted file mode 100644 index d220bba..0000000 --- a/OnixLabs.Core/Units/DataSize.Equatable.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Core.Units; - -public readonly partial struct DataSize : IEquatable> -{ - /// - /// Compares two instances of to determine whether their values are equal. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// Returns true if the two specified instances are equal; otherwise, false. - public static bool Equals(DataSize left, DataSize right) - { - return left.Bits == right.Bits; - } - - /// - /// Indicates whether the current object is equal to another object of the same type. - /// - /// An object to compare with this object. - /// Returns true if the current object is equal to the other parameter; otherwise, false. - public bool Equals(DataSize other) - { - return Equals(this, other); - } - - /// - /// Checks for equality between this instance and another object. - /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public override bool Equals(object? obj) - { - return obj is DataSize other && Equals(other); - } - - /// - /// Serves as a hash code function for this instance. - /// - /// A hash code for this instance. - public override int GetHashCode() - { - return HashCode.Combine(Bits); - } - - /// - /// Performs an equality check between two object instances. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(DataSize left, DataSize right) - { - return Equals(left, right); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(DataSize left, DataSize right) - { - return !Equals(left, right); - } -} diff --git a/OnixLabs.Core/Units/DataSize.From.cs b/OnixLabs.Core/Units/DataSize.From.cs deleted file mode 100644 index f073afc..0000000 --- a/OnixLabs.Core/Units/DataSize.From.cs +++ /dev/null @@ -1,424 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Numerics; - -namespace OnixLabs.Core.Units; - -public readonly partial struct DataSize -{ - /// - /// Creates a new instance from the specified bit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified bit value. - public static DataSize FromBits(T value) - { - return new DataSize(value); - } - - /// - /// Creates a new instance from the specified nibble value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified nibble value. - public static DataSize FromNibbles(T value) - { - return FromBits(value * BitsPerNibble); - } - - /// - /// Creates a new instance from the specified byte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified byte value. - public static DataSize FromBytes(T value) - { - return FromBits(value * BitsPerByte); - } - - /// - /// Creates a new instance from the specified word value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified word value. - public static DataSize FromWords(T value) - { - return FromBits(value * BitsPerWord); - } - - /// - /// Creates a new instance from the specified double-word value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified double-word value. - public static DataSize FromDoubleWords(T value) - { - return FromBits(value * BitsPerDoubleWord); - } - - /// - /// Creates a new instance from the specified quad-word value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified quad-word value. - public static DataSize FromQuadWords(T value) - { - return FromBits(value * BitsPerQuadWord); - } - - /// - /// Creates a new instance from the specified kilobit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified kilobit value. - public static DataSize FromKiloBits(T value) - { - return GetUnscaledBits(value, DecimalThousand, 1); - } - - /// - /// Creates a new instance from the specified kibibit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified kibibit value. - public static DataSize FromKibiBits(T value) - { - return GetUnscaledBits(value, BinaryThousand, 1); - } - - /// - /// Creates a new instance from the specified kilobyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified kilobyte value. - public static DataSize FromKiloBytes(T value) - { - return GetUnscaledBytes(value, DecimalThousand, 1); - } - - /// - /// Creates a new instance from the specified kibibyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified kibibyte value. - public static DataSize FromKibiBytes(T value) - { - return GetUnscaledBytes(value, BinaryThousand, 1); - } - - /// - /// Creates a new instance from the specified megabit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified megabit value. - public static DataSize FromMegaBits(T value) - { - return GetUnscaledBits(value, DecimalThousand, 2); - } - - /// - /// Creates a new instance from the specified mebibit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified mebibit value. - public static DataSize FromMebiBits(T value) - { - return GetUnscaledBits(value, BinaryThousand, 2); - } - - /// - /// Creates a new instance from the specified megabyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified megabyte value. - public static DataSize FromMegaBytes(T value) - { - return GetUnscaledBytes(value, DecimalThousand, 2); - } - - /// - /// Creates a new instance from the specified mebibyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified mebibyte value. - public static DataSize FromMebiBytes(T value) - { - return GetUnscaledBytes(value, BinaryThousand, 2); - } - - /// - /// Creates a new instance from the specified gigabit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified gigabit value. - public static DataSize FromGigaBits(T value) - { - return GetUnscaledBits(value, DecimalThousand, 3); - } - - /// - /// Creates a new instance from the specified gibibit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified gibibit value. - public static DataSize FromGibiBits(T value) - { - return GetUnscaledBits(value, BinaryThousand, 3); - } - - /// - /// Creates a new instance from the specified gigabyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified gigabyte value. - public static DataSize FromGigaBytes(T value) - { - return GetUnscaledBytes(value, DecimalThousand, 3); - } - - /// - /// Creates a new instance from the specified gibibyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified gibibyte value. - public static DataSize FromGibiBytes(T value) - { - return GetUnscaledBytes(value, BinaryThousand, 3); - } - - /// - /// Creates a new instance from the specified terabit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified terabit value. - public static DataSize FromTeraBits(T value) - { - return GetUnscaledBits(value, DecimalThousand, 4); - } - - /// - /// Creates a new instance from the specified tebibit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified tebibit value. - public static DataSize FromTebiBits(T value) - { - return GetUnscaledBits(value, BinaryThousand, 4); - } - - /// - /// Creates a new instance from the specified terabyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified terabyte value. - public static DataSize FromTeraBytes(T value) - { - return GetUnscaledBytes(value, DecimalThousand, 4); - } - - /// - /// Creates a new instance from the specified tebibyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified tebibyte value. - public static DataSize FromTebiBytes(T value) - { - return GetUnscaledBytes(value, BinaryThousand, 4); - } - - /// - /// Creates a new instance from the specified petabit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified petabit value. - public static DataSize FromPetaBits(T value) - { - return GetUnscaledBits(value, DecimalThousand, 5); - } - - /// - /// Creates a new instance from the specified pebibit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified pebibit value. - public static DataSize FromPebiBits(T value) - { - return GetUnscaledBits(value, BinaryThousand, 5); - } - - /// - /// Creates a new instance from the specified petabyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified petabyte value. - public static DataSize FromPetaBytes(T value) - { - return GetUnscaledBytes(value, DecimalThousand, 5); - } - - /// - /// Creates a new instance from the specified pebibyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified pebibyte value. - public static DataSize FromPebiBytes(T value) - { - return GetUnscaledBytes(value, BinaryThousand, 5); - } - - /// - /// Creates a new instance from the specified exabit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified exabit value. - public static DataSize FromExaBits(T value) - { - return GetUnscaledBits(value, DecimalThousand, 6); - } - - /// - /// Creates a new instance from the specified exbibit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified exbibit value. - public static DataSize FromExbiBits(T value) - { - return GetUnscaledBits(value, BinaryThousand, 6); - } - - /// - /// Creates a new instance from the specified exabyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified exabyte value. - public static DataSize FromExaBytes(T value) - { - return GetUnscaledBytes(value, DecimalThousand, 6); - } - - /// - /// Creates a new instance from the specified exbibyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified exbibyte value. - public static DataSize FromExbiBytes(T value) - { - return GetUnscaledBytes(value, BinaryThousand, 6); - } - - /// - /// Creates a new instance from the specified zettabit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified zettabit value. - public static DataSize FromZettaBits(T value) - { - return GetUnscaledBits(value, DecimalThousand, 7); - } - - /// - /// Creates a new instance from the specified zebibit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified zebibit value. - public static DataSize FromZebiBits(T value) - { - return GetUnscaledBits(value, BinaryThousand, 7); - } - - /// - /// Creates a new instance from the specified zettabyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified zettabyte value. - public static DataSize FromZettaBytes(T value) - { - return GetUnscaledBytes(value, DecimalThousand, 7); - } - - /// - /// Creates a new instance from the specified zebibyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified zebibyte value. - public static DataSize FromZebiBytes(T value) - { - return GetUnscaledBytes(value, BinaryThousand, 7); - } - - /// - /// Creates a new instance from the specified yottabit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified yottabit value. - public static DataSize FromYottaBits(T value) - { - return GetUnscaledBits(value, DecimalThousand, 8); - } - - /// - /// Creates a new instance from the specified yobibit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified yobibit value. - public static DataSize FromYobiBits(T value) - { - return GetUnscaledBits(value, BinaryThousand, 8); - } - - /// - /// Creates a new instance from the specified yottabyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified yottabyte value. - public static DataSize FromYottaBytes(T value) - { - return GetUnscaledBytes(value, DecimalThousand, 8); - } - - /// - /// Creates a new instance from the specified yobibyte value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified yobibyte value. - public static DataSize FromYobiBytes(T value) - { - return GetUnscaledBytes(value, BinaryThousand, 8); - } - - /// - /// Gets the number of bits in the specified value. - /// - /// The value from which to calculate the number of bits. - /// A value equalling either or to raise. - /// The exponent to raise the thousand value by. - /// Returns the number of bits in the specified value. - private static DataSize GetUnscaledBits(T value, T thousand, int exponent) - { - return new DataSize(value * GenericMath.Pow(thousand, exponent)); - } - - /// - /// Gets the number of bits in the specified value. - /// - /// The value from which to calculate the number of bits. - /// A value equalling either or to raise. - /// The exponent to raise the thousand value by. - /// Returns the number of bits in the specified value. - private static DataSize GetUnscaledBytes(T value, T thousand, int exponent) - { - return new DataSize(value * (GenericMath.Pow(thousand, exponent) * BitsPerByte)); - } -} diff --git a/OnixLabs.Core/Units/DataSize.Static.Arithmetic.cs b/OnixLabs.Core/Units/DataSize.Static.Arithmetic.cs deleted file mode 100644 index ed569e5..0000000 --- a/OnixLabs.Core/Units/DataSize.Static.Arithmetic.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.Units; - -/// -/// Provides functionality for managing instances. -/// -public static partial class DataSize -{ - /// - /// Computes the sum of the specified values. - /// - /// The left-hand value to add to. - /// The right-hand value to add. - /// The underlying type that represents the unit. - /// Returns the sum of the specified values. - public static DataSize Add(DataSize left, DataSize right) where T : IFloatingPoint - { - return DataSize.Add(left, right); - } - - /// - /// Computes the difference between the specified values. - /// - /// The left-hand value to subtract from. - /// The right-hand value to subtract. - /// The underlying type that represents the unit. - /// Returns the difference between the specified values. - public static DataSize Subtract(DataSize left, DataSize right) where T : IFloatingPoint - { - return DataSize.Subtract(left, right); - } - - /// - /// Computes the product of the specified values. - /// - /// The left-hand value to multiply. - /// The right-hand value to multiply by. - /// The underlying type that represents the unit. - /// Returns the product of the specified values. - public static DataSize Multiply(DataSize left, DataSize right) where T : IFloatingPoint - { - return DataSize.Multiply(left, right); - } - - /// - /// Computes the quotient of the specified values. - /// - /// The left-hand value to divide. - /// The right-hand value to divide by. - /// The underlying type that represents the unit. - /// Returns the quotient of the specified values. - public static DataSize Divide(DataSize left, DataSize right) where T : IFloatingPoint - { - return DataSize.Divide(left, right); - } -} diff --git a/OnixLabs.Core/Units/DataSize.Static.Comparison.cs b/OnixLabs.Core/Units/DataSize.Static.Comparison.cs deleted file mode 100644 index b6adc6b..0000000 --- a/OnixLabs.Core/Units/DataSize.Static.Comparison.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.Units; - -public static partial class DataSize -{ - /// - /// Compares two values and returns an integer that indicates - /// whether the left-hand value is less than, equal to, or greater than the right-hand value. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// The underlying type that represents the unit. - /// Returns a value that indicates the relative order of the objects being compared. - public static int Compare(DataSize left, DataSize right) where T : IFloatingPoint - { - return DataSize.Compare(left, right); - } - - /// - /// Compares two instances of to determine whether their values are equal. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// The underlying type that represents the unit. - /// Returns true if the two specified instances are equal; otherwise, false. - public static bool Equals(DataSize left, DataSize right) where T : IFloatingPoint - { - return DataSize.Equals(left, right); - } -} diff --git a/OnixLabs.Core/Units/DataSize.Static.From.cs b/OnixLabs.Core/Units/DataSize.Static.From.cs deleted file mode 100644 index 40a2c46..0000000 --- a/OnixLabs.Core/Units/DataSize.Static.From.cs +++ /dev/null @@ -1,438 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.Units; - -public static partial class DataSize -{ - /// - /// Creates a new instance from the specified bit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified bit value. - public static DataSize FromBits(T value) where T : IFloatingPoint - { - return DataSize.FromBits(value); - } - - /// - /// Creates a new instance from the specified nibble value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified nibble value. - public static DataSize FromNibbles(T value) where T : IFloatingPoint - { - return DataSize.FromNibbles(value); - } - - /// - /// Creates a new instance from the specified byte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified byte value. - public static DataSize FromBytes(T value) where T : IFloatingPoint - { - return DataSize.FromBytes(value); - } - - /// - /// Creates a new instance from the specified word value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified word value. - public static DataSize FromWords(T value) where T : IFloatingPoint - { - return DataSize.FromWords(value); - } - - /// - /// Creates a new instance from the specified double-word value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified double-word value. - public static DataSize FromDoubleWords(T value) where T : IFloatingPoint - { - return DataSize.FromDoubleWords(value); - } - - /// - /// Creates a new instance from the specified quad-word value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified quad-word value. - public static DataSize FromQuadWords(T value) where T : IFloatingPoint - { - return DataSize.FromQuadWords(value); - } - - /// - /// Creates a new instance from the specified kilobit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified kilobit value. - public static DataSize FromKiloBits(T value) where T : IFloatingPoint - { - return DataSize.FromKiloBits(value); - } - - /// - /// Creates a new instance from the specified kibibit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified kibibit value. - public static DataSize FromKibiBits(T value) where T : IFloatingPoint - { - return DataSize.FromKibiBits(value); - } - - /// - /// Creates a new instance from the specified kilobyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified kilobyte value. - public static DataSize FromKiloBytes(T value) where T : IFloatingPoint - { - return DataSize.FromKiloBytes(value); - } - - /// - /// Creates a new instance from the specified kibibyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified kibibyte value. - public static DataSize FromKibiBytes(T value) where T : IFloatingPoint - { - return DataSize.FromKibiBytes(value); - } - - /// - /// Creates a new instance from the specified megabit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified megabit value. - public static DataSize FromMegaBits(T value) where T : IFloatingPoint - { - return DataSize.FromMegaBits(value); - } - - /// - /// Creates a new instance from the specified mebibit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified mebibit value. - public static DataSize FromMebiBits(T value) where T : IFloatingPoint - { - return DataSize.FromMebiBits(value); - } - - /// - /// Creates a new instance from the specified megabyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified megabyte value. - public static DataSize FromMegaBytes(T value) where T : IFloatingPoint - { - return DataSize.FromMegaBytes(value); - } - - /// - /// Creates a new instance from the specified mebibyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified mebibyte value. - public static DataSize FromMebiBytes(T value) where T : IFloatingPoint - { - return DataSize.FromMebiBytes(value); - } - - /// - /// Creates a new instance from the specified gigabit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified gigabit value. - public static DataSize FromGigaBits(T value) where T : IFloatingPoint - { - return DataSize.FromGigaBits(value); - } - - /// - /// Creates a new instance from the specified gibibit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified gibibit value. - public static DataSize FromGibiBits(T value) where T : IFloatingPoint - { - return DataSize.FromGibiBits(value); - } - - /// - /// Creates a new instance from the specified gigabyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified gigabyte value. - public static DataSize FromGigaBytes(T value) where T : IFloatingPoint - { - return DataSize.FromGigaBytes(value); - } - - /// - /// Creates a new instance from the specified gibibyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified gibibyte value. - public static DataSize FromGibiBytes(T value) where T : IFloatingPoint - { - return DataSize.FromGibiBytes(value); - } - - /// - /// Creates a new instance from the specified terabit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified terabit value. - public static DataSize FromTeraBits(T value) where T : IFloatingPoint - { - return DataSize.FromTeraBits(value); - } - - /// - /// Creates a new instance from the specified tebibit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified tebibit value. - public static DataSize FromTebiBits(T value) where T : IFloatingPoint - { - return DataSize.FromTebiBits(value); - } - - /// - /// Creates a new instance from the specified terabyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified terabyte value. - public static DataSize FromTeraBytes(T value) where T : IFloatingPoint - { - return DataSize.FromTeraBytes(value); - } - - /// - /// Creates a new instance from the specified tebibyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified tebibyte value. - public static DataSize FromTebiBytes(T value) where T : IFloatingPoint - { - return DataSize.FromTebiBytes(value); - } - - /// - /// Creates a new instance from the specified petabit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified petabit value. - public static DataSize FromPetaBits(T value) where T : IFloatingPoint - { - return DataSize.FromPetaBits(value); - } - - /// - /// Creates a new instance from the specified pebibit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified pebibit value. - public static DataSize FromPebiBits(T value) where T : IFloatingPoint - { - return DataSize.FromPebiBits(value); - } - - /// - /// Creates a new instance from the specified petabyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified petabyte value. - public static DataSize FromPetaBytes(T value) where T : IFloatingPoint - { - return DataSize.FromPetaBytes(value); - } - - /// - /// Creates a new instance from the specified pebibyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified pebibyte value. - public static DataSize FromPebiBytes(T value) where T : IFloatingPoint - { - return DataSize.FromPebiBytes(value); - } - - /// - /// Creates a new instance from the specified exabit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified exabit value. - public static DataSize FromExaBits(T value) where T : IFloatingPoint - { - return DataSize.FromExaBits(value); - } - - /// - /// Creates a new instance from the specified exbibit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified exbibit value. - public static DataSize FromExbiBits(T value) where T : IFloatingPoint - { - return DataSize.FromExbiBits(value); - } - - /// - /// Creates a new instance from the specified exabyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified exabyte value. - public static DataSize FromExaBytes(T value) where T : IFloatingPoint - { - return DataSize.FromExaBytes(value); - } - - /// - /// Creates a new instance from the specified exbibyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified exbibyte value. - public static DataSize FromExbiBytes(T value) where T : IFloatingPoint - { - return DataSize.FromExbiBytes(value); - } - - /// - /// Creates a new instance from the specified zettabit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified zettabit value. - public static DataSize FromZettaBits(T value) where T : IFloatingPoint - { - return DataSize.FromZettaBits(value); - } - - /// - /// Creates a new instance from the specified zebibit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified zebibit value. - public static DataSize FromZebiBits(T value) where T : IFloatingPoint - { - return DataSize.FromZebiBits(value); - } - - /// - /// Creates a new instance from the specified zettabyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified zettabyte value. - public static DataSize FromZettaBytes(T value) where T : IFloatingPoint - { - return DataSize.FromZettaBytes(value); - } - - /// - /// Creates a new instance from the specified zebibyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified zebibyte value. - public static DataSize FromZebiBytes(T value) where T : IFloatingPoint - { - return DataSize.FromZebiBytes(value); - } - - /// - /// Creates a new instance from the specified yottabit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified yottabit value. - public static DataSize FromYottaBits(T value) where T : IFloatingPoint - { - return DataSize.FromYottaBits(value); - } - - /// - /// Creates a new instance from the specified yobibit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified yobibit value. - public static DataSize FromYobiBits(T value) where T : IFloatingPoint - { - return DataSize.FromYobiBits(value); - } - - /// - /// Creates a new instance from the specified yottabyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified yottabyte value. - public static DataSize FromYottaBytes(T value) where T : IFloatingPoint - { - return DataSize.FromYottaBytes(value); - } - - /// - /// Creates a new instance from the specified yobibyte value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified yobibyte value. - public static DataSize FromYobiBytes(T value) where T : IFloatingPoint - { - return DataSize.FromYobiBytes(value); - } -} diff --git a/OnixLabs.Core/Units/DataSize.To.cs b/OnixLabs.Core/Units/DataSize.To.cs deleted file mode 100644 index f831da8..0000000 --- a/OnixLabs.Core/Units/DataSize.To.cs +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Globalization; - -namespace OnixLabs.Core.Units; - -public readonly partial struct DataSize : IFormattable -{ - /// - /// Formats the value of the current instance using the specified format. - /// Valid formats for include: - /// - /// FormatDescription - /// bBits - /// nNibbles - /// BBytes - /// WWords - /// DWDoubleWords - /// QWQuadWords - /// KbKiloBits - /// KibKibiBits - /// KBKiloBytes - /// KiBKibiBytes - /// MbMegaBits - /// MibMebiBits - /// MBMegaBytes - /// MiBMebiBytes - /// GbGigaBits - /// GibGibiBits - /// GBGigaBytes - /// GiBGibiBytes - /// TbTeraBits - /// TibTebiBits - /// TBTeraBytes - /// TiBTebiBytes - /// PbPetaBits - /// PibPebiBits - /// PBPetaBytes - /// PiBPebiBytes - /// EbExaBits - /// EibExbiBits - /// EBExaBytes - /// EiBExbiBytes - /// ZbZettaBits - /// ZibZebiBits - /// ZBZettaBytes - /// ZiBZebiBytes - /// YbYottaBits - /// YibYobiBits - /// YBYottaBytes - /// YiBYobiBytes - /// - /// - /// The format to use, or null to use the default format. - /// The provider to use to format the value. - /// Returns the value of the current instance in the specified format. - /// If the specified format is invalid. - public string ToString(string? format, IFormatProvider? formatProvider) - { - string formatOrDefault = format ?? DefaultFormat; - IFormatProvider formatProviderOrDefault = formatProvider ?? CultureInfo.CurrentCulture; - - T value = formatOrDefault switch - { - "b" => Bits, - "n" => Nibbles, - "B" => Bytes, - "W" => Words, - "DW" => DoubleWords, - "QW" => QuadWords, - "Kb" => KiloBits, - "Kib" => KibiBits, - "KB" => KiloBytes, - "KiB" => KibiBytes, - "Mb" => MegaBits, - "Mib" => MebiBits, - "MB" => MegaBytes, - "MiB" => MebiBytes, - "Gb" => GigaBits, - "Gib" => GibiBits, - "GB" => GigaBytes, - "GiB" => GibiBytes, - "Tb" => TeraBits, - "Tib" => TebiBits, - "TB" => TeraBytes, - "TiB" => TebiBytes, - "Pb" => PetaBits, - "Pib" => PebiBits, - "PB" => PetaBytes, - "PiB" => PebiBytes, - "Eb" => ExaBits, - "Eib" => ExbiBits, - "EB" => ExaBytes, - "EiB" => ExbiBytes, - "Zb" => ZettaBits, - "Zib" => ZebiBits, - "ZB" => ZettaBytes, - "ZiB" => ZebiBytes, - "Yb" => YottaBits, - "Yib" => YobiBits, - "YB" => YottaBytes, - "YiB" => YobiBytes, - _ => throw new ArgumentException($"Invalid format specifier: {format}.") - }; - - return $"{value.ToString("R", formatProviderOrDefault)} {formatOrDefault}"; - } - - /// - /// Formats the value of the current instance using the specified format. - /// Valid formats for include: - /// - /// FormatDescription - /// bBits - /// nNibbles - /// BBytes - /// WWords - /// DWDoubleWords - /// QWQuadWords - /// KbKiloBits - /// KibKibiBits - /// KBKiloBytes - /// KiBKibiBytes - /// MbMegaBits - /// MibMebiBits - /// MBMegaBytes - /// MiBMebiBytes - /// GbGigaBits - /// GibGibiBits - /// GBGigaBytes - /// GiBGibiBytes - /// TbTeraBits - /// TibTebiBits - /// TBTeraBytes - /// TiBTebiBytes - /// PbPetaBits - /// PibPebiBits - /// PBPetaBytes - /// PiBPebiBytes - /// EbExaBits - /// EibExbiBits - /// EBExaBytes - /// EiBExbiBytes - /// ZbZettaBits - /// ZibZebiBits - /// ZBZettaBytes - /// ZiBZebiBytes - /// YbYottaBits - /// YibYobiBits - /// YBYottaBytes - /// YiBYobiBytes - /// - /// - /// The format to use, or null to use the default format. - /// The provider to use to format the value. - /// Returns the value of the current instance in the specified format. - /// If the specified format is invalid. - public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) - { - return ToString(format.ToString(), formatProvider); - } - - /// - /// Formats the value of the current instance using the default format. - /// - /// Returns the value of the current instance in the specified format. - /// If the specified format is invalid. - public override string ToString() - { - return ToString(DefaultFormat); - } -} diff --git a/OnixLabs.Core/Units/DataSize.cs b/OnixLabs.Core/Units/DataSize.cs deleted file mode 100644 index c7560a0..0000000 --- a/OnixLabs.Core/Units/DataSize.cs +++ /dev/null @@ -1,247 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; -using OnixLabs.Core.Numerics; - -namespace OnixLabs.Core.Units; - -/// -/// Represents a unit of DataSize. -/// -/// The underlying type that represents the current unit. -public readonly partial struct DataSize where T : IFloatingPoint -{ - /// - /// Initializes a new instance of the struct. - /// - /// The initial DataSize value in Bits. - private DataSize(T bits) - { - Require(bits >= T.Zero, $"Cannot initialize {nameof(DataSize)} from negative value.", nameof(bits)); - Bits = bits; - } - - /// - /// Gets the current in bits. - /// - public T Bits { get; } - - /// - /// Gets the current in nibbles. - /// - public T Nibbles => Bits / BitsPerNibble; - - /// - /// Gets the current in bytes. - /// - public T Bytes => Bits / BitsPerByte; - - /// - /// Gets the current in words. - /// - public T Words => Bits / BitsPerWord; - - /// - /// Gets the current in double-words. - /// - public T DoubleWords => Bits / BitsPerDoubleWord; - - /// - /// Gets the current in quad-words. - /// - public T QuadWords => Bits / BitsPerQuadWord; - - /// - /// Gets the current in kilobits. - /// - public T KiloBits => GetScaledBits(DecimalThousand, 1); - - /// - /// Gets the current in kibibits. - /// - public T KibiBits => GetScaledBits(BinaryThousand, 1); - - /// - /// Gets the current in kilobytes. - /// - public T KiloBytes => GetScaledBytes(DecimalThousand, 1); - - /// - /// Gets the current in kibibytes. - /// - public T KibiBytes => GetScaledBytes(BinaryThousand, 1); - - /// - /// Gets the current in megabits. - /// - public T MegaBits => GetScaledBits(DecimalThousand, 2); - - /// - /// Gets the current in mebibits. - /// - public T MebiBits => GetScaledBits(BinaryThousand, 2); - - /// - /// Gets the current in megabytes. - /// - public T MegaBytes => GetScaledBytes(DecimalThousand, 2); - - /// - /// Gets the current in mebibytes. - /// - public T MebiBytes => GetScaledBytes(BinaryThousand, 2); - - /// - /// Gets the current in gigabits. - /// - public T GigaBits => GetScaledBits(DecimalThousand, 3); - - /// - /// Gets the current in gibibits. - /// - public T GibiBits => GetScaledBits(BinaryThousand, 3); - - /// - /// Gets the current in gigbytes. - /// - public T GigaBytes => GetScaledBytes(DecimalThousand, 3); - - /// - /// Gets the current in gibibytes. - /// - public T GibiBytes => GetScaledBytes(BinaryThousand, 3); - - /// - /// Gets the current in terabits. - /// - public T TeraBits => GetScaledBits(DecimalThousand, 4); - - /// - /// Gets the current in tebibits. - /// - public T TebiBits => GetScaledBits(BinaryThousand, 4); - - /// - /// Gets the current in terabytes. - /// - public T TeraBytes => GetScaledBytes(DecimalThousand, 4); - - /// - /// Gets the current in tebibytes. - /// - public T TebiBytes => GetScaledBytes(BinaryThousand, 4); - - /// - /// Gets the current in petabits. - /// - public T PetaBits => GetScaledBits(DecimalThousand, 5); - - /// - /// Gets the current in pebibits. - /// - public T PebiBits => GetScaledBits(BinaryThousand, 5); - - /// - /// Gets the current in petabytes. - /// - public T PetaBytes => GetScaledBytes(DecimalThousand, 5); - - /// - /// Gets the current in pebibytes. - /// - public T PebiBytes => GetScaledBytes(BinaryThousand, 5); - - /// - /// Gets the current in exabits. - /// - public T ExaBits => GetScaledBits(DecimalThousand, 6); - - /// - /// Gets the current in exbibits. - /// - public T ExbiBits => GetScaledBits(BinaryThousand, 6); - - /// - /// Gets the current in exabytes. - /// - public T ExaBytes => GetScaledBytes(DecimalThousand, 6); - - /// - /// Gets the current in exbibytes. - /// - public T ExbiBytes => GetScaledBytes(BinaryThousand, 6); - - /// - /// Gets the current in zettabits. - /// - public T ZettaBits => GetScaledBits(DecimalThousand, 7); - - /// - /// Gets the current in zebibits. - /// - public T ZebiBits => GetScaledBits(BinaryThousand, 7); - - /// - /// Gets the current in zettabytes. - /// - public T ZettaBytes => GetScaledBytes(DecimalThousand, 7); - - /// - /// Gets the current in zebibytes. - /// - public T ZebiBytes => GetScaledBytes(BinaryThousand, 7); - - /// - /// Gets the current in yottabits. - /// - public T YottaBits => GetScaledBits(DecimalThousand, 8); - - /// - /// Gets the current in yobibits. - /// - public T YobiBits => GetScaledBits(BinaryThousand, 8); - - /// - /// Gets the current in yottabytes. - /// - public T YottaBytes => GetScaledBytes(DecimalThousand, 8); - - /// - /// Gets the current in yobibytes. - /// - public T YobiBytes => GetScaledBytes(BinaryThousand, 8); - - /// - /// Calculates the current divided by the specified power. - /// - /// A value equalling either or to raise. - /// The exponent to raise the thousand value by. - /// Returns the current divided by the specified power. - private T GetScaledBits(T thousand, int exponent) - { - return Bits / GenericMath.Pow(thousand, exponent); - } - - /// - /// Calculates the current divided by the specified power. - /// - /// A value equalling either or to raise. - /// The exponent to raise the thousand value by. - /// Returns the current divided by the specified power. - private T GetScaledBytes(T thousand, int exponent) - { - return Bits / (GenericMath.Pow(thousand, exponent) * BitsPerByte); - } -} diff --git a/OnixLabs.Core/Units/Temperature.Arithmetic.cs b/OnixLabs.Core/Units/Temperature.Arithmetic.cs deleted file mode 100644 index e7e0576..0000000 --- a/OnixLabs.Core/Units/Temperature.Arithmetic.cs +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Core.Units; - -public readonly partial struct Temperature -{ - /// - /// Computes the sum of the specified values. - /// - /// The left-hand value to add to. - /// The right-hand value to add. - /// Returns the sum of the specified values. - public static Temperature Add(Temperature left, Temperature right) - { - return new Temperature(left.Kelvin + right.Kelvin); - } - - /// - /// Computes the difference between the specified values. - /// - /// The left-hand value to subtract from. - /// The right-hand value to subtract. - /// Returns the difference between the specified values. - public static Temperature Subtract(Temperature left, Temperature right) - { - return new Temperature(left.Kelvin - right.Kelvin); - } - - /// - /// Computes the product of the specified values. - /// - /// The left-hand value to multiply. - /// The right-hand value to multiply by. - /// Returns the product of the specified values. - public static Temperature Multiply(Temperature left, Temperature right) - { - return new Temperature(left.Kelvin * right.Kelvin); - } - - /// - /// Computes the quotient of the specified values. - /// - /// The left-hand value to divide. - /// The right-hand value to divide by. - /// Returns the quotient of the specified values. - public static Temperature Divide(Temperature left, Temperature right) - { - return new Temperature(left.Kelvin / right.Kelvin); - } - - /// - /// Computes the sum of the specified values. - /// - /// The left-hand value to add to. - /// The right-hand value to add. - /// Returns the sum of the specified values. - public static Temperature operator +(Temperature left, Temperature right) - { - return Add(left, right); - } - - /// - /// Computes the difference between the specified values. - /// - /// The left-hand value to subtract from. - /// The right-hand value to subtract. - /// Returns the difference between the specified values. - public static Temperature operator -(Temperature left, Temperature right) - { - return Subtract(left, right); - } - - /// - /// Computes the product of the specified values. - /// - /// The left-hand value to multiply. - /// The right-hand value to multiply by. - /// Returns the product of the specified values. - public static Temperature operator *(Temperature left, Temperature right) - { - return Multiply(left, right); - } - - /// - /// Computes the quotient of the specified values. - /// - /// The left-hand value to divide. - /// The right-hand value to divide by. - /// Returns the quotient of the specified values. - public static Temperature operator /(Temperature left, Temperature right) - { - return Divide(left, right); - } -} diff --git a/OnixLabs.Core/Units/Temperature.Equatable.cs b/OnixLabs.Core/Units/Temperature.Equatable.cs deleted file mode 100644 index 44ec236..0000000 --- a/OnixLabs.Core/Units/Temperature.Equatable.cs +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Core.Units; - -public readonly partial struct Temperature : IEquatable> -{ - /// - /// Compares two instances of to determine whether their values are equal. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// Returns true if the two specified instances are equal; otherwise, false. - public static bool Equals(Temperature left, Temperature right) - { - return left.Kelvin == right.Kelvin; - } - - /// - /// Indicates whether the current object is equal to another object of the same type. - /// - /// An object to compare with this object. - /// Returns true if the current object is equal to the other parameter; otherwise, false. - public bool Equals(Temperature other) - { - return Equals(this, other); - } - - /// - /// Checks for equality between this instance and another object. - /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. - public override bool Equals(object? obj) - { - return obj is Temperature other && Equals(other); - } - - /// - /// Serves as a hash code function for this instance. - /// - /// A hash code for this instance. - public override int GetHashCode() - { - return HashCode.Combine(Kelvin); - } - - /// - /// Performs an equality check between two object instances. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// True if the instances are equal; otherwise, false. - public static bool operator ==(Temperature left, Temperature right) - { - return Equals(left, right); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// True if the instances are not equal; otherwise, false. - public static bool operator !=(Temperature left, Temperature right) - { - return !Equals(left, right); - } -} diff --git a/OnixLabs.Core/Units/Temperature.From.cs b/OnixLabs.Core/Units/Temperature.From.cs deleted file mode 100644 index 5be9b19..0000000 --- a/OnixLabs.Core/Units/Temperature.From.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Core.Units; - -public readonly partial struct Temperature -{ - /// - /// Creates a new instance from the specified Celsius value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified Celsius value. - public static Temperature FromCelsius(T value) - { - return new Temperature(value + T.CreateChecked(273.15)); - } - - /// - /// Creates a new instance from the specified Delisle value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified Delisle value. - public static Temperature FromDelisle(T value) - { - return new Temperature(T.CreateChecked(373.15) - value * T.CreateChecked(2) / T.CreateChecked(3)); - } - - /// - /// Creates a new instance from the specified Fahrenheit value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified Fahrenheit value. - public static Temperature FromFahrenheit(T value) - { - return new Temperature((value + T.CreateChecked(459.67)) * T.CreateChecked(5) / T.CreateChecked(9)); - } - - /// - /// Creates a new instance from the specified Kelvin value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified Kelvin value. - public static Temperature FromKelvin(T value) - { - return new Temperature(value); - } - - /// - /// Creates a new instance from the specified Newton value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified Newton value. - public static Temperature FromNewton(T value) - { - return new Temperature(value * (T.CreateChecked(100) / T.CreateChecked(33)) + T.CreateChecked(273.15)); - } - - /// - /// Creates a new instance from the specified Reaumur value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified Reaumur value. - public static Temperature FromReaumur(T value) - { - return new Temperature(value * T.CreateChecked(1.25) + T.CreateChecked(273.15)); - } - - /// - /// Creates a new instance from the specified Rankine value. - /// - /// The value from which to create a new instance. - /// Returns a new instance from the specified Rankine value. - public static Temperature FromRankine(T value) - { - return new Temperature(value / T.CreateChecked(1.8)); - } -} diff --git a/OnixLabs.Core/Units/Temperature.Static.Arithmetic.cs b/OnixLabs.Core/Units/Temperature.Static.Arithmetic.cs deleted file mode 100644 index 715e13b..0000000 --- a/OnixLabs.Core/Units/Temperature.Static.Arithmetic.cs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.Units; - -/// -/// Provides functionality for managing instances. -/// -public static partial class Temperature -{ - /// - /// Computes the sum of the specified values. - /// - /// The left-hand value to add to. - /// The right-hand value to add. - /// The underlying type that represents the unit. - /// Returns the sum of the specified values. - public static Temperature Add(Temperature left, Temperature right) where T : IFloatingPoint - { - return Temperature.Add(left, right); - } - - /// - /// Computes the difference between the specified values. - /// - /// The left-hand value to subtract from. - /// The right-hand value to subtract. - /// The underlying type that represents the unit. - /// Returns the difference between the specified values. - public static Temperature Subtract(Temperature left, Temperature right) where T : IFloatingPoint - { - return Temperature.Subtract(left, right); - } - - /// - /// Computes the product of the specified values. - /// - /// The left-hand value to multiply. - /// The right-hand value to multiply by. - /// The underlying type that represents the unit. - /// Returns the product of the specified values. - public static Temperature Multiply(Temperature left, Temperature right) where T : IFloatingPoint - { - return Temperature.Multiply(left, right); - } - - /// - /// Computes the quotient of the specified values. - /// - /// The left-hand value to divide. - /// The right-hand value to divide by. - /// The underlying type that represents the unit. - /// Returns the quotient of the specified values. - public static Temperature Divide(Temperature left, Temperature right) where T : IFloatingPoint - { - return Temperature.Divide(left, right); - } -} diff --git a/OnixLabs.Core/Units/Temperature.Static.Comparison.cs b/OnixLabs.Core/Units/Temperature.Static.Comparison.cs deleted file mode 100644 index 1985987..0000000 --- a/OnixLabs.Core/Units/Temperature.Static.Comparison.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.Units; - -public static partial class Temperature -{ - /// - /// Compares two values and returns an integer that indicates - /// whether the left-hand value is less than, equal to, or greater than the right-hand value. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// The underlying type that represents the unit. - /// Returns a value that indicates the relative order of the objects being compared. - public static int Compare(Temperature left, Temperature right) where T : IFloatingPoint - { - return Temperature.Compare(left, right); - } - - /// - /// Compares two instances of to determine whether their values are equal. - /// - /// The left-hand value to compare. - /// The right-hand value to compare. - /// The underlying type that represents the unit. - /// Returns true if the two specified instances are equal; otherwise, false. - public static bool Equals(Temperature left, Temperature right) where T : IFloatingPoint - { - return Temperature.Equals(left, right); - } -} diff --git a/OnixLabs.Core/Units/Temperature.Static.From.cs b/OnixLabs.Core/Units/Temperature.Static.From.cs deleted file mode 100644 index aa5f7e2..0000000 --- a/OnixLabs.Core/Units/Temperature.Static.From.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.Units; - -public static partial class Temperature -{ - /// - /// Creates a new instance from the specified Celsius value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified Celsius value. - public static Temperature FromCelsius(T value) where T : IFloatingPoint - { - return Temperature.FromCelsius(value); - } - - /// - /// Creates a new instance from the specified Delisle value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified Delisle value. - public static Temperature FromDelisle(T value) where T : IFloatingPoint - { - return Temperature.FromDelisle(value); - } - - /// - /// Creates a new instance from the specified Fahrenheit value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified Fahrenheit value. - public static Temperature FromFahrenheit(T value) where T : IFloatingPoint - { - return Temperature.FromFahrenheit(value); - } - - /// - /// Creates a new instance from the specified Kelvin value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified Kelvin value. - public static Temperature FromKelvin(T value) where T : IFloatingPoint - { - return Temperature.FromKelvin(value); - } - - /// - /// Creates a new instance from the specified Newton value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified Newton value. - public static Temperature FromNewton(T value) where T : IFloatingPoint - { - return Temperature.FromNewton(value); - } - - /// - /// Creates a new instance from the specified Reaumur value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified Reaumur value. - public static Temperature FromReaumur(T value) where T : IFloatingPoint - { - return Temperature.FromReaumur(value); - } - - /// - /// Creates a new instance from the specified Rankine value. - /// - /// The value from which to create a new instance. - /// The underlying type that represents the unit. - /// Returns a new instance from the specified Rankine value. - public static Temperature FromRankine(T value) where T : IFloatingPoint - { - return Temperature.FromRankine(value); - } -} diff --git a/OnixLabs.Core/Units/Temperature.To.cs b/OnixLabs.Core/Units/Temperature.To.cs deleted file mode 100644 index 3debaad..0000000 --- a/OnixLabs.Core/Units/Temperature.To.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Globalization; - -namespace OnixLabs.Core.Units; - -public readonly partial struct Temperature : IFormattable -{ - /// - /// Formats the value of the current instance using the specified format. - /// Valid formats for include: - /// - /// FormatDescription - /// KKelvin - /// CCelsius - /// DDelisle - /// FFahrenheit - /// NNewton - /// RReaumur - /// RaRankine - /// - /// - /// The format to use, or null to use the default format. - /// The provider to use to format the value. - /// Returns the value of the current instance in the specified format. - /// If the specified format is invalid. - public string ToString(string? format, IFormatProvider? formatProvider = null) - { - string formatOrDefault = format ?? DefaultFormat; - IFormatProvider formatProviderOrDefault = formatProvider ?? CultureInfo.CurrentCulture; - - T value = formatOrDefault switch - { - "K" => Kelvin, - "C" => Celsius, - "D" => Delisle, - "F" => Fahrenheit, - "N" => Newton, - "R" => Reaumur, - "Ra" => Rankine, - _ => throw new ArgumentException($"Invalid format specifier: {format}.") - }; - - return $"{value.ToString("R", formatProviderOrDefault)}°{formatOrDefault}"; - } - - /// - /// Formats the value of the current instance using the specified format. - /// Valid formats for include: - /// - /// FormatDescription - /// KKelvin - /// CCelsius - /// DDelisle - /// FFahrenheit - /// NNewton - /// RReaumur - /// RaRankine - /// - /// - /// The format to use, or null to use the default format. - /// The provider to use to format the value. - /// Returns the value of the current instance in the specified format. - /// If the specified format is invalid. - public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) - { - return ToString(format.ToString(), formatProvider); - } - - /// - /// Formats the value of the current instance using the default format. - /// - /// Returns the value of the current instance in the specified format. - /// If the specified format is invalid. - public override string ToString() - { - return ToString(DefaultFormat); - } -} diff --git a/OnixLabs.Core/Units/Temperature.cs b/OnixLabs.Core/Units/Temperature.cs deleted file mode 100644 index 1b1d516..0000000 --- a/OnixLabs.Core/Units/Temperature.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.Units; - -/// -/// Represents a unit of temperature. -/// -/// The underlying type that represents the current unit. -public readonly partial struct Temperature where T : IFloatingPoint -{ - /// - /// Initializes a new instance of the struct. - /// - /// The initial temperature value in Kelvin. - private Temperature(T kelvin) - { - Kelvin = kelvin; - } - - /// - /// Gets the current in Kelvin. - /// - public T Kelvin { get; } - - /// - /// Gets the current in Celsius. - /// - public T Celsius => Kelvin - T.CreateChecked(273.15); - - /// - /// Gets the current in Delisle. - /// - public T Delisle => (T.CreateChecked(373.15) - Kelvin) * T.CreateChecked(1.5); - - /// - /// Gets the current in Fahrenheit. - /// - public T Fahrenheit => Kelvin * T.CreateChecked(1.8) - T.CreateChecked(459.67); - - /// - /// Gets the current in Newton. - /// - public T Newton => (Kelvin - T.CreateChecked(273.15)) * T.CreateChecked(0.33); - - /// - /// Gets the current in Reaumur. - /// - public T Reaumur => (Kelvin - T.CreateChecked(273.15)) * T.CreateChecked(0.8); - - /// - /// Gets the current in Rankine. - /// - public T Rankine => Kelvin * T.CreateChecked(1.8); -} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticAbsDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticAbsDataAttribute.cs new file mode 100644 index 0000000..1481511 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticAbsDataAttribute.cs @@ -0,0 +1,27 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticAbsDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal value in TestDataGenerator.GenerateRandomValues()) + yield return [value]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticAdditionDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticAdditionDataAttribute.cs new file mode 100644 index 0000000..b31cea4 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticAdditionDataAttribute.cs @@ -0,0 +1,32 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticAdditionDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal left in TestDataGenerator.GenerateScaledValues()) + foreach (decimal right in TestDataGenerator.GenerateScaledValues()) + yield return [left, right, Guid.NewGuid()]; + + foreach (decimal left in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MinValue)) + foreach (decimal right in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MaxValue)) + yield return [left, right, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticDivisionDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticDivisionDataAttribute.cs new file mode 100644 index 0000000..22c87f6 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticDivisionDataAttribute.cs @@ -0,0 +1,40 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticDivisionDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (MidpointRounding mode in TestDataGenerator.GetMidpointRoundingModes()) + foreach (decimal left in TestDataGenerator.GenerateScaledValues()) + foreach (decimal right in TestDataGenerator.GenerateScaledValues()) + { + if (right is 0) continue; + yield return [left, right, mode, Guid.NewGuid()]; + } + + foreach (MidpointRounding mode in TestDataGenerator.GetMidpointRoundingModes()) + foreach (decimal left in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MinValue)) + foreach (decimal right in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MaxValue)) + { + if (right is 0) continue; + yield return [left, right, mode, Guid.NewGuid()]; + } + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticModulusDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticModulusDataAttribute.cs new file mode 100644 index 0000000..85be7d2 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticModulusDataAttribute.cs @@ -0,0 +1,28 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticModulusDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal left in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MinValue)) + foreach (decimal right in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MaxValue)) + yield return [left, right, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticMultiplicationDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticMultiplicationDataAttribute.cs new file mode 100644 index 0000000..a35d844 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticMultiplicationDataAttribute.cs @@ -0,0 +1,32 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticMultiplicationDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal left in TestDataGenerator.GenerateScaledValues()) + foreach (decimal right in TestDataGenerator.GenerateScaledValues()) + yield return [left, right, Guid.NewGuid()]; + + foreach (decimal left in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MinValue)) + foreach (decimal right in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MaxValue)) + yield return [left, right, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticPowDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticPowDataAttribute.cs new file mode 100644 index 0000000..8affc1d --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticPowDataAttribute.cs @@ -0,0 +1,205 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticPowDataAttribute : DataAttribute +{ + private static readonly (decimal Value, int Exponent, decimal Expected)[] Data = + [ + (0m, 1, 0m), + (0m, 2, 0m), + (0m, 3, 0m), + (0m, 4, 0m), + (0m, 5, 0m), + (0m, 10, 0m), + (0m, 28, 0m), + (1m, 1, 1m), + (1m, 2, 1m), + (1m, 3, 1m), + (1m, 4, 1m), + (1m, 5, 1m), + (1m, 10, 1m), + (1m, 28, 1m), + (2m, 1, 2m), + (2m, 2, 4m), + (2m, 3, 8m), + (2m, 4, 16m), + (2m, 5, 32m), + (2m, 10, 1024m), + (3m, 1, 3m), + (3m, 2, 9m), + (3m, 3, 27m), + (3m, 4, 81m), + (3m, 5, 243m), + (3m, 10, 59049m), + (4m, 1, 4m), + (4m, 2, 16m), + (4m, 3, 64m), + (4m, 4, 256m), + (4m, 5, 1024m), + (4m, 10, 1048576m), + (5m, 1, 5m), + (5m, 2, 25m), + (5m, 3, 125m), + (5m, 4, 625m), + (5m, 5, 3125m), + (5m, 10, 9765625m), + (10m, 1, 10m), + (10m, 2, 100m), + (10m, 3, 1000m), + (10m, 4, 10000m), + (10m, 5, 100000m), + (10m, 10, 10000000000m), + (10m, 28, 10000000000000000000000000000m), + (-1m, 1, -1m), + (-1m, 2, -1m), + (-1m, 3, -1m), + (-1m, 4, -1m), + (-1m, 5, -1m), + (-1m, 10, -1m), + (-1m, 28, -1m), + (-2m, 1, -2m), + (-2m, 2, -4m), + (-2m, 3, -8m), + (-2m, 4, -16m), + (-2m, 5, -32m), + (-2m, 10, -1024m), + (-3m, 1, -3m), + (-3m, 2, -9m), + (-3m, 3, -27m), + (-3m, 4, -81m), + (-3m, 5, -243m), + (-3m, 10, -59049m), + (-4m, 1, -4m), + (-4m, 2, -16m), + (-4m, 3, -64m), + (-4m, 4, -256m), + (-4m, 5, -1024m), + (-4m, 10, -1048576m), + (-5m, 1, -5m), + (-5m, 2, -25m), + (-5m, 3, -125m), + (-5m, 4, -625m), + (-5m, 5, -3125m), + (-5m, 10, -9765625m), + (-10m, 1, -10m), + (-10m, 2, -100m), + (-10m, 3, -1000m), + (-10m, 4, -10000m), + (-10m, 5, -100000m), + (-10m, 10, -10000000000m), + (-10m, 28, -10000000000000000000000000000m), + (1m, -1, 1m), + (1m, -2, 1m), + (1m, -3, 1m), + (1m, -4, 1m), + (1m, -5, 1m), + (1m, -10, 1m), + (1m, -28, 1m), + (2.0m, -1, 0.5m), + (2.00m, -1, 0.50m), + (2.000m, -1, 0.500m), + (2.0000m, -1, 0.5000m), + (2.00000m, -1, 0.50000m), + (2.0000000000m, -1, 0.5000000000m), + (2.0000000000000000000000000000m, -1, 0.5000000000000000000000000000m), + (2.0m, -2, 0.2m), + (2.00m, -2, 0.25m), + (2.000m, -2, 0.250m), + (2.0000m, -2, 0.2500m), + (2.00000m, -2, 0.25000m), + (2.0000000000m, -2, 0.2500000000m), + (2.0000000000000000000000000000m, -2, 0.2500000000000000000000000000m), + (2.0m, -3, 0.1m), + (2.00m, -3, 0.12m), + (2.000m, -3, 0.125m), + (2.0000m, -3, 0.1250m), + (2.00000m, -3, 0.12500m), + (2.0000000000m, -3, 0.1250000000m), + (2.000000000000000000000000000000m, -3, 0.1250000000000000000000000000m), + (2.0m, -4, 0.1m), + (2.00m, -4, 0.06m), + (2.000m, -4, 0.062m), + (2.0000m, -4, 0.0625m), + (2.00000m, -4, 0.06250m), + (2.0000000000m, -4, 0.0625000000m), + (2.0000000000000000000000000000m, -4, 0.0625000000000000000000000000m), + (2.0m, -5, 0.0m), + (2.00m, -5, 0.03m), + (2.000m, -5, 0.031m), + (2.0000m, -5, 0.0312m), + (2.00000m, -5, 0.03125m), + (2.0000000000m, -5, 0.0312500000m), + (2.0000000000000000000000000000m, -5, 0.0312500000000000000000000000m), + (2.0m, -10, 0.0m), + (2.00m, -10, 0.00m), + (2.000m, -10, 0.001m), + (2.0000m, -10, 0.0010m), + (2.00000m, -10, 0.00098m), + (2.0000000000m, -10, 0.0009765625m), + (2.0000000000000000000000000000m, -10, 0.0009765625000000000000000000m), + (3.0m, -1, 0.3m), + (3.00m, -1, 0.33m), + (3.000m, -1, 0.333m), + (3.0000m, -1, 0.3333m), + (3.00000m, -1, 0.33333m), + (3.0000000000m, -1, 0.3333333333m), + (3.0000000000000000000000000000m, -1, 0.3333333333333333333333333333m), + (3.0m, -2, 0.1m), + (3.00m, -2, 0.11m), + (3.000m, -2, 0.111m), + (3.0000m, -2, 0.1111m), + (3.00000m, -2, 0.11111m), + (3.0000000000m, -2, 0.1111111111m), + (3.0000000000000000000000000000m, -2, 0.1111111111111111111111111111m), + (3.0m, -3, 0.0m), + (3.00m, -3, 0.04m), + (3.000m, -3, 0.037m), + (3.0000m, -3, 0.0370m), + (3.00000m, -3, 0.03704m), + (3.0000000000m, -3, 0.0370370370m), + (3.0000000000000000000000000000m, -3, 0.0370370370370370370370370370m), + (3.0m, -4, 0.0m), + (3.00m, -4, 0.01m), + (3.000m, -4, 0.012m), + (3.0000m, -4, 0.0123m), + (3.00000m, -4, 0.01235m), + (3.0000000000m, -4, 0.0123456790m), + (3.0000000000000000000000000000m, -4, 0.0123456790123456790123456790m), + (3.0m, -5, 0.0m), + (3.00m, -5, 0.00m), + (3.000m, -5, 0.004m), + (3.0000m, -5, 0.0041m), + (3.00000m, -5, 0.00412m), + (3.0000000000m, -5, 0.0041152263m), + (3.000000000000000000000000000000m, -5, 0.004115226337448559670781893004m), + (3.0m, -10, 0.0m), + (3.00m, -10, 0.00m), + (3.000m, -10, 0.000m), + (3.0000m, -10, 0.0000m), + (3.00000m, -10, 0.00002m), + (3.0000000000m, -10, 0.0000169351m), + (3.0000000000000000000000000000m, -10, 0.000016935087808430286711036597m) + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach ((decimal value, int exponent, decimal expected) in Data) + yield return [value, exponent, expected]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticRoundDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticRoundDataAttribute.cs new file mode 100644 index 0000000..be55d9b --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticRoundDataAttribute.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticRoundDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + IEnumerable values = Enumerable.Empty() + .Concat(TestDataGenerator.GenerateConstantValues()) + .Concat(TestDataGenerator.GenerateScaledMaxValues()) + .Concat(TestDataGenerator.GenerateScaledMinValues()) + .Concat(TestDataGenerator.GenerateRandomValues()); + + foreach (decimal value in values) + foreach (int scale in TestDataGenerator.GenerateScaleValues()) + foreach (MidpointRounding mode in TestDataGenerator.GetMidpointRoundingModes()) + yield return [value, scale, mode, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticScaleDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticScaleDataAttribute.cs new file mode 100644 index 0000000..b582a74 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticScaleDataAttribute.cs @@ -0,0 +1,59 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticScaleDataAttribute : DataAttribute +{ + private static readonly int[] Integers = [0, 1, 2, 3, 123, 123456789, -1, -2, -3, -123, -123456789]; + + private static readonly int[] IntegerScales = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + + private static readonly decimal[] Decimals = + [ + +0.1234567890987654321000000000m, + +1.1234567890987654321000000000m, + -0.1234567890987654321000000000m, + -1.1234567890987654321000000000m + ]; + + private static readonly int[] DecimalScales = + [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (int value in Integers) + foreach (int initialScale in IntegerScales) + foreach (MidpointRounding rounding in Enum.GetValues()) + foreach (int desiredScale in IntegerScales) + { + decimal initial = value.ToDecimal(initialScale, ScaleMode.Integral); + decimal expected = value.ToDecimal(desiredScale, ScaleMode.Integral); + yield return [initial, desiredScale, rounding, expected]; + } + + foreach (decimal value in Decimals) + foreach (int scale in DecimalScales) + foreach (MidpointRounding rounding in Enum.GetValues()) + { + decimal expected = decimal.Round(value, scale, rounding); + yield return [value, scale, rounding, expected]; + } + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticSubtractionDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticSubtractionDataAttribute.cs new file mode 100644 index 0000000..7eec7e1 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticSubtractionDataAttribute.cs @@ -0,0 +1,32 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticSubtractionDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal left in TestDataGenerator.GenerateScaledValues()) + foreach (decimal right in TestDataGenerator.GenerateScaledValues()) + yield return [left, right, Guid.NewGuid()]; + + foreach (decimal left in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MinValue)) + foreach (decimal right in TestDataGenerator.GenerateRandomValues(count: 10, seed: int.MaxValue)) + yield return [left, right, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticTrimDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticTrimDataAttribute.cs new file mode 100644 index 0000000..59dbb6f --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticTrimDataAttribute.cs @@ -0,0 +1,42 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticTrimDataAttribute : DataAttribute +{ + private static readonly (decimal Value, decimal Expected)[] Data = + [ + (0.0m, 0m), + (1.0m, 1m), + (1.0000000000000000000000000000m, 1m), + (1.10m, 1.1m), + (1.1000000000000000000000000000m, 1.1m), + (123.4560000000000000000000000000m, 123.456m), + (-1.0m, -1m), + (-1.0000000000000000000000000000m, -1m), + (-1.10m, -1.1m), + (-1.1000000000000000000000000000m, -1.1m), + (-123.4560000000000000000000000000m, -123.456m) + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach ((decimal value, decimal expected) in Data) + yield return [value, expected]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticTruncateDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticTruncateDataAttribute.cs new file mode 100644 index 0000000..925df4f --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticTruncateDataAttribute.cs @@ -0,0 +1,30 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticTruncateDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal value in TestDataGenerator.GenerateScaledValues()) + yield return [value, Guid.NewGuid()]; + + foreach (decimal value in TestDataGenerator.GenerateRandomValues()) + yield return [value, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticUnaryAdditionDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticUnaryAdditionDataAttribute.cs new file mode 100644 index 0000000..6d6189b --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticUnaryAdditionDataAttribute.cs @@ -0,0 +1,27 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticUnaryAdditionDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal value in TestDataGenerator.GenerateRandomValues()) + yield return [value]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticUnarySubtractionDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticUnarySubtractionDataAttribute.cs new file mode 100644 index 0000000..d345e19 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalArithmeticUnarySubtractionDataAttribute.cs @@ -0,0 +1,27 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalArithmeticUnarySubtractionDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal value in TestDataGenerator.GenerateRandomValues()) + yield return [value]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalIeee754BinaryDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalIeee754BinaryDataAttribute.cs new file mode 100644 index 0000000..1ab8a0f --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalIeee754BinaryDataAttribute.cs @@ -0,0 +1,217 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalIeee754BinaryDataAttribute : DataAttribute +{ + private static readonly double[] Data = + [ + // General test values + 0.0, double.MinValue, double.MaxValue, double.E, double.Epsilon, double.Pi, double.Tau, + + // Positive one with positive exponent + 1.0, 1e+1, 1e+2, 1e+3, 1e+4, 1e+5, 1e+6, 1e+7, 1e+8, 1e+9, 1e+10, + 1e+11, 1e+12, 1e+13, 1e+14, 1e+15, 1e+16, 1e+17, 1e+18, 1e+19, 1e+20, 1e+100, 1e+308, + + // Positive one with negative exponent + 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, 1e-10, + 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19, 1e-20, 1e-100, 1e-320, + + // Positive two with positive exponent + 2.0, 2e+1, 2e+2, 2e+3, 2e+4, 2e+5, 2e+6, 2e+7, 2e+8, 2e+9, 2e+10, + 2e+11, 2e+12, 2e+13, 2e+14, 2e+15, 2e+16, 2e+17, 2e+18, 2e+19, 2e+20, 2e+100, 2e+307, + + // Positive two with negative exponent + 2e-1, 2e-2, 2e-3, 2e-4, 2e-5, 2e-6, 2e-7, 2e-8, 2e-9, 2e-10, + 2e-11, 2e-12, 2e-13, 2e-14, 2e-15, 2e-16, 2e-17, 2e-18, 2e-19, 2e-20, 2e-100, 2e-320, + + // Positive three with positive exponent + 3.0, 3e+1, 3e+2, 3e+3, 3e+4, 3e+5, 3e+6, 3e+7, 3e+8, 3e+9, 3e+10, + 3e+11, 3e+12, 3e+13, 3e+14, 3e+15, 3e+16, 3e+17, 3e+18, 3e+19, 3e+20, 3e+100, 3e+307, + + // Positive three with negative exponent + 3e-1, 3e-2, 3e-3, 3e-4, 3e-5, 3e-6, 3e-7, 3e-8, 3e-9, 3e-10, + 3e-11, 3e-12, 3e-13, 3e-14, 3e-15, 3e-16, 3e-17, 3e-18, 3e-19, 3e-20, 3e-100, 3e-320, + + // Positive four with positive exponent + 4.0, 4e+1, 4e+2, 4e+3, 4e+4, 4e+5, 4e+6, 4e+7, 4e+8, 4e+9, 4e+10, + 4e+11, 4e+12, 4e+13, 4e+14, 4e+15, 4e+16, 4e+17, 4e+18, 4e+19, 4e+20, 4e+100, 4e+307, + + // Positive four with negative exponent + 4e-1, 4e-2, 4e-3, 4e-4, 4e-5, 4e-6, 4e-7, 4e-8, 4e-9, 4e-10, + 4e-11, 4e-12, 4e-13, 4e-14, 4e-15, 4e-16, 4e-17, 4e-18, 4e-19, 4e-20, 4e-100, 4e-320, + + // Positive five with positive exponent + 5.0, 5e+1, 5e+2, 5e+3, 5e+4, 5e+5, 5e+6, 5e+7, 5e+8, 5e+9, 5e+10, + 5e+11, 5e+12, 5e+13, 5e+14, 5e+15, 5e+16, 5e+17, 5e+18, 5e+19, 5e+20, 5e+100, 5e+307, + + // Positive five with negative exponent + 5e-1, 5e-2, 5e-3, 5e-4, 5e-5, 5e-6, 5e-7, 5e-8, 5e-9, 5e-10, + 5e-11, 5e-12, 5e-13, 5e-14, 5e-15, 5e-16, 5e-17, 5e-18, 5e-19, 5e-20, 5e-100, 5e-320, + + // Positive six with positive exponent + 6.0, 6e+1, 6e+2, 6e+3, 6e+4, 6e+5, 6e+6, 6e+7, 6e+8, 6e+9, 6e+10, + 6e+11, 6e+12, 6e+13, 6e+14, 6e+15, 6e+16, 6e+17, 6e+18, 6e+19, 6e+20, 6e+100, 6e+307, + + // Positive six with negative exponent + 6e-1, 6e-2, 6e-3, 6e-4, 6e-5, 6e-6, 6e-7, 6e-8, 6e-9, 6e-10, + 6e-11, 6e-12, 6e-13, 6e-14, 6e-15, 6e-16, 6e-17, 6e-18, 6e-19, 6e-20, 6e-100, 6e-320, + + // Positive seven with positive exponent + 7.0, 7e+1, 7e+2, 7e+3, 7e+4, 7e+5, 7e+6, 7e+7, 7e+8, 7e+9, 7e+10, + 7e+11, 7e+12, 7e+13, 7e+14, 7e+15, 7e+16, 7e+17, 7e+18, 7e+19, 7e+20, 7e+100, 7e+307, + + // Positive seven with negative exponent + 7e-1, 7e-2, 7e-3, 7e-4, 7e-5, 7e-6, 7e-7, 7e-8, 7e-9, 7e-10, + 7e-11, 7e-12, 7e-13, 7e-14, 7e-15, 7e-16, 7e-17, 7e-18, 7e-19, 7e-20, 7e-100, 7e-320, + + // Positive eight with positive exponent + 8.0, 8e+1, 8e+2, 8e+3, 8e+4, 8e+5, 8e+6, 8e+7, 8e+8, 8e+9, 8e+10, + 8e+11, 8e+12, 8e+13, 8e+14, 8e+15, 8e+16, 8e+17, 8e+18, 8e+19, 8e+20, 8e+100, 8e+307, + + // Positive eight with negative exponent + 8e-1, 8e-2, 8e-3, 8e-4, 8e-5, 8e-6, 8e-7, 8e-8, 8e-9, 8e-10, + 8e-11, 8e-12, 8e-13, 8e-14, 8e-15, 8e-16, 8e-17, 8e-18, 8e-19, 8e-20, 8e-100, 8e-320, + + // Positive nine with positive exponent + 9.0, 9e+1, 9e+2, 9e+3, 9e+4, 9e+5, 9e+6, 9e+7, 9e+8, 9e+9, 9e+10, + 9e+11, 9e+12, 9e+13, 9e+14, 9e+15, 9e+16, 9e+17, 9e+18, 9e+19, 9e+20, 9e+100, 9e+307, + + // Positive nine with negative exponent + 9e-1, 9e-2, 9e-3, 9e-4, 9e-5, 9e-6, 9e-7, 9e-8, 9e-9, 9e-10, + 9e-11, 9e-12, 9e-13, 9e-14, 9e-15, 9e-16, 9e-17, 9e-18, 9e-19, 9e-20, 9e-100, 9e-320, + + // Negative one with positive exponent + -1.0, -1e+1, -1e+2, -1e+3, -1e+4, -1e+5, -1e+6, -1e+7, -1e+8, -1e+9, -1e+10, + -1e+11, -1e+12, -1e+13, -1e+14, -1e+15, -1e+16, -1e+17, -1e+18, -1e+19, -1e+20, -1e+100, -1e+308, + + // Negative one with negative exponent + -1e-1, -1e-2, -1e-3, -1e-4, -1e-5, -1e-6, -1e-7, -1e-8, -1e-9, -1e-10, + -1e-11, -1e-12, -1e-13, -1e-14, -1e-15, -1e-16, -1e-17, -1e-18, -1e-19, -1e-20, -1e-100, -1e-320, + + // Negative two with positive exponent + -2.0, -2e+1, -2e+2, -2e+3, -2e+4, -2e+5, -2e+6, -2e+7, -2e+8, -2e+9, -2e+10, + -2e+11, -2e+12, -2e+13, -2e+14, -2e+15, -2e+16, -2e+17, -2e+18, -2e+19, -2e+20, -2e+100, -2e+307, + + // Negative two with negative exponent + -2e-1, -2e-2, -2e-3, -2e-4, -2e-5, -2e-6, -2e-7, -2e-8, -2e-9, -2e-10, + -2e-11, -2e-12, -2e-13, -2e-14, -2e-15, -2e-16, -2e-17, -2e-18, -2e-19, -2e-20, -2e-100, -2e-320, + + // Negative three with positive exponent + -3.0, -3e+1, -3e+2, -3e+3, -3e+4, -3e+5, -3e+6, -3e+7, -3e+8, -3e+9, -3e+10, + -3e+11, -3e+12, -3e+13, -3e+14, -3e+15, -3e+16, -3e+17, -3e+18, -3e+19, -3e+20, -3e+100, -3e+307, + + // Negative three with negative exponent + -3e-1, -3e-2, -3e-3, -3e-4, -3e-5, -3e-6, -3e-7, -3e-8, -3e-9, -3e-10, + -3e-11, -3e-12, -3e-13, -3e-14, -3e-15, -3e-16, -3e-17, -3e-18, -3e-19, -3e-20, -3e-100, -3e-320, + + // Negative four with positive exponent + -4.0, -4e+1, -4e+2, -4e+3, -4e+4, -4e+5, -4e+6, -4e+7, -4e+8, -4e+9, -4e+10, + -4e+11, -4e+12, -4e+13, -4e+14, -4e+15, -4e+16, -4e+17, -4e+18, -4e+19, -4e+20, -4e+100, -4e+307, + + // Negative four with negative exponent + -4e-1, -4e-2, -4e-3, -4e-4, -4e-5, -4e-6, -4e-7, -4e-8, -4e-9, -4e-10, + -4e-11, -4e-12, -4e-13, -4e-14, -4e-15, -4e-16, -4e-17, -4e-18, -4e-19, -4e-20, -4e-100, -4e-320, + + // Negative five with positive exponent + -5.0, -5e+1, -5e+2, -5e+3, -5e+4, -5e+5, -5e+6, -5e+7, -5e+8, -5e+9, -5e+10, + -5e+11, -5e+12, -5e+13, -5e+14, -5e+15, -5e+16, -5e+17, -5e+18, -5e+19, -5e+20, -5e+100, -5e+307, + + // Negative five with negative exponent + -5e-1, -5e-2, -5e-3, -5e-4, -5e-5, -5e-6, -5e-7, -5e-8, -5e-9, -5e-10, + -5e-11, -5e-12, -5e-13, -5e-14, -5e-15, -5e-16, -5e-17, -5e-18, -5e-19, -5e-20, -5e-100, -5e-320, + + // Negative six with positive exponent + -6.0, -6e+1, -6e+2, -6e+3, -6e+4, -6e+5, -6e+6, -6e+7, -6e+8, -6e+9, -6e+10, + -6e+11, -6e+12, -6e+13, -6e+14, -6e+15, -6e+16, -6e+17, -6e+18, -6e+19, -6e+20, -6e+100, -6e+307, + + // Negative six with negative exponent + -6e-1, -6e-2, -6e-3, -6e-4, -6e-5, -6e-6, -6e-7, -6e-8, -6e-9, -6e-10, + -6e-11, -6e-12, -6e-13, -6e-14, -6e-15, -6e-16, -6e-17, -6e-18, -6e-19, -6e-20, -6e-100, -6e-320, + + // Negative seven with positive exponent + -7.0, -7e+1, -7e+2, -7e+3, -7e+4, -7e+5, -7e+6, -7e+7, -7e+8, -7e+9, -7e+10, + -7e+11, -7e+12, -7e+13, -7e+14, -7e+15, -7e+16, -7e+17, -7e+18, -7e+19, -7e+20, -7e+100, -7e+307, + + // Negative seven with negative exponent + -7e-1, -7e-2, -7e-3, -7e-4, -7e-5, -7e-6, -7e-7, -7e-8, -7e-9, -7e-10, + -7e-11, -7e-12, -7e-13, -7e-14, -7e-15, -7e-16, -7e-17, -7e-18, -7e-19, -7e-20, -7e-100, -7e-320, + + // Negative eight with positive exponent + -8.0, -8e+1, -8e+2, -8e+3, -8e+4, -8e+5, -8e+6, -8e+7, -8e+8, -8e+9, -8e+10, + -8e+11, -8e+12, -8e+13, -8e+14, -8e+15, -8e+16, -8e+17, -8e+18, -8e+19, -8e+20, -8e+100, -8e+307, + + // Negative eight with negative exponent + -8e-1, -8e-2, -8e-3, -8e-4, -8e-5, -8e-6, -8e-7, -8e-8, -8e-9, -8e-10, + -8e-11, -8e-12, -8e-13, -8e-14, -8e-15, -8e-16, -8e-17, -8e-18, -8e-19, -8e-20, -8e-100, -8e-320, + + // Negative nine with positive exponent + -9.0, -9e+1, -9e+2, -9e+3, -9e+4, -9e+5, -9e+6, -9e+7, -9e+8, -9e+9, -9e+10, + -9e+11, -9e+12, -9e+13, -9e+14, -9e+15, -9e+16, -9e+17, -9e+18, -9e+19, -9e+20, -9e+100, -9e+307, + + // Negative nine with negative exponent + -9e-1, -9e-2, -9e-3, -9e-4, -9e-5, -9e-6, -9e-7, -9e-8, -9e-9, -9e-10, + -9e-11, -9e-12, -9e-13, -9e-14, -9e-15, -9e-16, -9e-17, -9e-18, -9e-19, -9e-20, -9e-100, -9e-320, + + // Positive point shifting + 1234567890123456, + 123456789012345.6, + 12345678901234.56, + 1234567890123.456, + 123456789012.3456, + 12345678901.23456, + 1234567890.123456, + 123456789.0123456, + 12345678.90123456, + 1234567.890123456, + 123456.7890123456, + 12345.67890123456, + 1234.567890123456, + 123.4567890123456, + 12.34567890123456, + 1.234567890123456, + + // Negative point shifting + -1234567890123456, + -123456789012345.6, + -12345678901234.56, + -1234567890123.456, + -123456789012.3456, + -12345678901.23456, + -1234567890.123456, + -123456789.0123456, + -12345678.90123456, + -1234567.890123456, + -123456.7890123456, + -12345.67890123456, + -1234.567890123456, + -123.4567890123456, + -12.34567890123456, + -1.234567890123456, + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (double value in Data) yield return [value, GetNumberFormattedAsInflatedFixedPoint(value)]; + } + + private static string GetNumberFormattedAsInflatedFixedPoint(double value) + { + return value.ToString("F5000").TrimEnd('0').TrimEnd('.'); + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalIeee754DecimalDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalIeee754DecimalDataAttribute.cs new file mode 100644 index 0000000..ffdf9cc --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalIeee754DecimalDataAttribute.cs @@ -0,0 +1,915 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalIeee754DecimalDataAttribute : DataAttribute +{ + private static readonly (double Value, string Expected)[] Data = + [ + (double.MinValue, + "-179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (double.MaxValue, + "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (double.E, "2.718281828459045"), + (double.Pi, "3.141592653589793"), + (0.0, "0"), + (1.0, "1"), + (1e+1, "10"), + (1e+2, "100"), + (1e+3, "1000"), + (1e+4, "10000"), + (1e+5, "100000"), + (1e+6, "1000000"), + (1e+7, "10000000"), + (1e+8, "100000000"), + (1e+9, "1000000000"), + (1e+10, "10000000000"), + (1e+11, "100000000000"), + (1e+12, "1000000000000"), + (1e+13, "10000000000000"), + (1e+14, "100000000000000"), + (1e+15, "1000000000000000"), + (1e+16, "10000000000000000"), + (1e+17, "100000000000000000"), + (1e+18, "1000000000000000000"), + (1e+19, "10000000000000000000"), + (1e+20, "100000000000000000000"), + (1e+100, "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (1e+308, + "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (1e-1, "0.1"), + (1e-2, "0.01"), + (1e-3, "0.001"), + (1e-4, "0.0001"), + (1e-5, "0.00001"), + (1e-6, "0.000001"), + (1e-7, "0.0000001"), + (1e-8, "0.00000001"), + (1e-9, "0.000000001"), + (1e-10, "0.0000000001"), + (1e-11, "0.00000000001"), + (1e-12, "0.000000000001"), + (1e-13, "0.0000000000001"), + (1e-14, "0.00000000000001"), + (1e-15, "0.000000000000001"), + (1e-16, "0.0000000000000001"), + (1e-17, "0.00000000000000001"), + (1e-18, "0.000000000000000001"), + (1e-19, "0.0000000000000000001"), + (1e-20, "0.00000000000000000001"), + (1e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"), + (1e-317, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"), + (2.0, "2"), + (2e+1, "20"), + (2e+2, "200"), + (2e+3, "2000"), + (2e+4, "20000"), + (2e+5, "200000"), + (2e+6, "2000000"), + (2e+7, "20000000"), + (2e+8, "200000000"), + (2e+9, "2000000000"), + (2e+10, "20000000000"), + (2e+11, "200000000000"), + (2e+12, "2000000000000"), + (2e+13, "20000000000000"), + (2e+14, "200000000000000"), + (2e+15, "2000000000000000"), + (2e+16, "20000000000000000"), + (2e+17, "200000000000000000"), + (2e+18, "2000000000000000000"), + (2e+19, "20000000000000000000"), + (2e+20, "200000000000000000000"), + (2e+100, "20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (2e+307, + "20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (2e-1, "0.2"), + (2e-2, "0.02"), + (2e-3, "0.002"), + (2e-4, "0.0002"), + (2e-5, "0.00002"), + (2e-6, "0.000002"), + (2e-7, "0.0000002"), + (2e-8, "0.00000002"), + (2e-9, "0.000000002"), + (2e-10, "0.0000000002"), + (2e-11, "0.00000000002"), + (2e-12, "0.000000000002"), + (2e-13, "0.0000000000002"), + (2e-14, "0.00000000000002"), + (2e-15, "0.000000000000002"), + (2e-16, "0.0000000000000002"), + (2e-17, "0.00000000000000002"), + (2e-18, "0.000000000000000002"), + (2e-19, "0.0000000000000000002"), + (2e-20, "0.00000000000000000002"), + (2e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"), + (2e-320, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"), + (3.0, "3"), + (3e+1, "30"), + (3e+2, "300"), + (3e+3, "3000"), + (3e+4, "30000"), + (3e+5, "300000"), + (3e+6, "3000000"), + (3e+7, "30000000"), + (3e+8, "300000000"), + (3e+9, "3000000000"), + (3e+10, "30000000000"), + (3e+11, "300000000000"), + (3e+12, "3000000000000"), + (3e+13, "30000000000000"), + (3e+14, "300000000000000"), + (3e+15, "3000000000000000"), + (3e+16, "30000000000000000"), + (3e+17, "300000000000000000"), + (3e+18, "3000000000000000000"), + (3e+19, "30000000000000000000"), + (3e+20, "300000000000000000000"), + (3e+100, "30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (3e+307, + "30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (3e-1, "0.3"), + (3e-2, "0.03"), + (3e-3, "0.003"), + (3e-4, "0.0003"), + (3e-5, "0.00003"), + (3e-6, "0.000003"), + (3e-7, "0.0000003"), + (3e-8, "0.00000003"), + (3e-9, "0.000000003"), + (3e-10, "0.0000000003"), + (3e-11, "0.00000000003"), + (3e-12, "0.000000000003"), + (3e-13, "0.0000000000003"), + (3e-14, "0.00000000000003"), + (3e-15, "0.000000000000003"), + (3e-16, "0.0000000000000003"), + (3e-17, "0.00000000000000003"), + (3e-18, "0.000000000000000003"), + (3e-19, "0.0000000000000000003"), + (3e-20, "0.00000000000000000003"), + (3e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), + (3e-320, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), + (4.0, "4"), + (4e+1, "40"), + (4e+2, "400"), + (4e+3, "4000"), + (4e+4, "40000"), + (4e+5, "400000"), + (4e+6, "4000000"), + (4e+7, "40000000"), + (4e+8, "400000000"), + (4e+9, "4000000000"), + (4e+10, "40000000000"), + (4e+11, "400000000000"), + (4e+12, "4000000000000"), + (4e+13, "40000000000000"), + (4e+14, "400000000000000"), + (4e+15, "4000000000000000"), + (4e+16, "40000000000000000"), + (4e+17, "400000000000000000"), + (4e+18, "4000000000000000000"), + (4e+19, "40000000000000000000"), + (4e+20, "400000000000000000000"), + (4e+100, "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (4e+307, + "40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (4e-1, "0.4"), + (4e-2, "0.04"), + (4e-3, "0.004"), + (4e-4, "0.0004"), + (4e-5, "0.00004"), + (4e-6, "0.000004"), + (4e-7, "0.0000004"), + (4e-8, "0.00000004"), + (4e-9, "0.000000004"), + (4e-10, "0.0000000004"), + (4e-11, "0.00000000004"), + (4e-12, "0.000000000004"), + (4e-13, "0.0000000000004"), + (4e-14, "0.00000000000004"), + (4e-15, "0.000000000000004"), + (4e-16, "0.0000000000000004"), + (4e-17, "0.00000000000000004"), + (4e-18, "0.000000000000000004"), + (4e-19, "0.0000000000000000004"), + (4e-20, "0.00000000000000000004"), + (4e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"), + (4e-320, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"), + (5.0, "5"), + (5e+1, "50"), + (5e+2, "500"), + (5e+3, "5000"), + (5e+4, "50000"), + (5e+5, "500000"), + (5e+6, "5000000"), + (5e+7, "50000000"), + (5e+8, "500000000"), + (5e+9, "5000000000"), + (5e+10, "50000000000"), + (5e+11, "500000000000"), + (5e+12, "5000000000000"), + (5e+13, "50000000000000"), + (5e+14, "500000000000000"), + (5e+15, "5000000000000000"), + (5e+16, "50000000000000000"), + (5e+17, "500000000000000000"), + (5e+18, "5000000000000000000"), + (5e+19, "50000000000000000000"), + (5e+20, "500000000000000000000"), + (5e+100, "50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (5e+307, + "50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (5e-1, "0.5"), + (5e-2, "0.05"), + (5e-3, "0.005"), + (5e-4, "0.0005"), + (5e-5, "0.00005"), + (5e-6, "0.000005"), + (5e-7, "0.0000005"), + (5e-8, "0.00000005"), + (5e-9, "0.000000005"), + (5e-10, "0.0000000005"), + (5e-11, "0.00000000005"), + (5e-12, "0.000000000005"), + (5e-13, "0.0000000000005"), + (5e-14, "0.00000000000005"), + (5e-15, "0.000000000000005"), + (5e-16, "0.0000000000000005"), + (5e-17, "0.00000000000000005"), + (5e-18, "0.000000000000000005"), + (5e-19, "0.0000000000000000005"), + (5e-20, "0.00000000000000000005"), + (5e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005"), + (5e-320, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005"), + (6.0, "6"), + (6e+1, "60"), + (6e+2, "600"), + (6e+3, "6000"), + (6e+4, "60000"), + (6e+5, "600000"), + (6e+6, "6000000"), + (6e+7, "60000000"), + (6e+8, "600000000"), + (6e+9, "6000000000"), + (6e+10, "60000000000"), + (6e+11, "600000000000"), + (6e+12, "6000000000000"), + (6e+13, "60000000000000"), + (6e+14, "600000000000000"), + (6e+15, "6000000000000000"), + (6e+16, "60000000000000000"), + (6e+17, "600000000000000000"), + (6e+18, "6000000000000000000"), + (6e+19, "60000000000000000000"), + (6e+20, "600000000000000000000"), + (6e+100, "60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (6e+307, + "60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (6e-1, "0.6"), + (6e-2, "0.06"), + (6e-3, "0.006"), + (6e-4, "0.0006"), + (6e-5, "0.00006"), + (6e-6, "0.000006"), + (6e-7, "0.0000006"), + (6e-8, "0.00000006"), + (6e-9, "0.000000006"), + (6e-10, "0.0000000006"), + (6e-11, "0.00000000006"), + (6e-12, "0.000000000006"), + (6e-13, "0.0000000000006"), + (6e-14, "0.00000000000006"), + (6e-15, "0.000000000000006"), + (6e-16, "0.0000000000000006"), + (6e-17, "0.00000000000000006"), + (6e-18, "0.000000000000000006"), + (6e-19, "0.0000000000000000006"), + (6e-20, "0.00000000000000000006"), + (6e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006"), + (6e-320, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006"), + (7.0, "7"), + (7e+1, "70"), + (7e+2, "700"), + (7e+3, "7000"), + (7e+4, "70000"), + (7e+5, "700000"), + (7e+6, "7000000"), + (7e+7, "70000000"), + (7e+8, "700000000"), + (7e+9, "7000000000"), + (7e+10, "70000000000"), + (7e+11, "700000000000"), + (7e+12, "7000000000000"), + (7e+13, "70000000000000"), + (7e+14, "700000000000000"), + (7e+15, "7000000000000000"), + (7e+16, "70000000000000000"), + (7e+17, "700000000000000000"), + (7e+18, "7000000000000000000"), + (7e+19, "70000000000000000000"), + (7e+20, "700000000000000000000"), + (7e+100, "70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (7e+307, + "70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (7e-1, "0.7"), + (7e-2, "0.07"), + (7e-3, "0.007"), + (7e-4, "0.0007"), + (7e-5, "0.00007"), + (7e-6, "0.000007"), + (7e-7, "0.0000007"), + (7e-8, "0.00000007"), + (7e-9, "0.000000007"), + (7e-10, "0.0000000007"), + (7e-11, "0.00000000007"), + (7e-12, "0.000000000007"), + (7e-13, "0.0000000000007"), + (7e-14, "0.00000000000007"), + (7e-15, "0.000000000000007"), + (7e-16, "0.0000000000000007"), + (7e-17, "0.00000000000000007"), + (7e-18, "0.000000000000000007"), + (7e-19, "0.0000000000000000007"), + (7e-20, "0.00000000000000000007"), + (7e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007"), + (7e-320, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007"), + (8.0, "8"), + (8e+1, "80"), + (8e+2, "800"), + (8e+3, "8000"), + (8e+4, "80000"), + (8e+5, "800000"), + (8e+6, "8000000"), + (8e+7, "80000000"), + (8e+8, "800000000"), + (8e+9, "8000000000"), + (8e+10, "80000000000"), + (8e+11, "800000000000"), + (8e+12, "8000000000000"), + (8e+13, "80000000000000"), + (8e+14, "800000000000000"), + (8e+15, "8000000000000000"), + (8e+16, "80000000000000000"), + (8e+17, "800000000000000000"), + (8e+18, "8000000000000000000"), + (8e+19, "80000000000000000000"), + (8e+20, "800000000000000000000"), + (8e+100, "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (8e+307, + "80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (8e-1, "0.8"), + (8e-2, "0.08"), + (8e-3, "0.008"), + (8e-4, "0.0008"), + (8e-5, "0.00008"), + (8e-6, "0.000008"), + (8e-7, "0.0000008"), + (8e-8, "0.00000008"), + (8e-9, "0.000000008"), + (8e-10, "0.0000000008"), + (8e-11, "0.00000000008"), + (8e-12, "0.000000000008"), + (8e-13, "0.0000000000008"), + (8e-14, "0.00000000000008"), + (8e-15, "0.000000000000008"), + (8e-16, "0.0000000000000008"), + (8e-17, "0.00000000000000008"), + (8e-18, "0.000000000000000008"), + (8e-19, "0.0000000000000000008"), + (8e-20, "0.00000000000000000008"), + (8e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008"), + (8e-320, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008"), + (9.0, "9"), + (9e+1, "90"), + (9e+2, "900"), + (9e+3, "9000"), + (9e+4, "90000"), + (9e+5, "900000"), + (9e+6, "9000000"), + (9e+7, "90000000"), + (9e+8, "900000000"), + (9e+9, "9000000000"), + (9e+10, "90000000000"), + (9e+11, "900000000000"), + (9e+12, "9000000000000"), + (9e+13, "90000000000000"), + (9e+14, "900000000000000"), + (9e+15, "9000000000000000"), + (9e+16, "90000000000000000"), + (9e+17, "900000000000000000"), + (9e+18, "9000000000000000000"), + (9e+19, "90000000000000000000"), + (9e+20, "900000000000000000000"), + (9e+100, "90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (9e+307, + "90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (9e-1, "0.9"), + (9e-2, "0.09"), + (9e-3, "0.009"), + (9e-4, "0.0009"), + (9e-5, "0.00009"), + (9e-6, "0.000009"), + (9e-7, "0.0000009"), + (9e-8, "0.00000009"), + (9e-9, "0.000000009"), + (9e-10, "0.0000000009"), + (9e-11, "0.00000000009"), + (9e-12, "0.000000000009"), + (9e-13, "0.0000000000009"), + (9e-14, "0.00000000000009"), + (9e-15, "0.000000000000009"), + (9e-16, "0.0000000000000009"), + (9e-17, "0.00000000000000009"), + (9e-18, "0.000000000000000009"), + (9e-19, "0.0000000000000000009"), + (9e-20, "0.00000000000000000009"), + (9e-100, "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"), + (9e-320, + "0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"), + (-1.0, "-1"), + (-1e+1, "-10"), + (-1e+2, "-100"), + (-1e+3, "-1000"), + (-1e+4, "-10000"), + (-1e+5, "-100000"), + (-1e+6, "-1000000"), + (-1e+7, "-10000000"), + (-1e+8, "-100000000"), + (-1e+9, "-1000000000"), + (-1e+10, "-10000000000"), + (-1e+11, "-100000000000"), + (-1e+12, "-1000000000000"), + (-1e+13, "-10000000000000"), + (-1e+14, "-100000000000000"), + (-1e+15, "-1000000000000000"), + (-1e+16, "-10000000000000000"), + (-1e+17, "-100000000000000000"), + (-1e+18, "-1000000000000000000"), + (-1e+19, "-10000000000000000000"), + (-1e+20, "-100000000000000000000"), + (-1e+100, "-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-1e+308, + "-100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-1e-1, "-0.1"), + (-1e-2, "-0.01"), + (-1e-3, "-0.001"), + (-1e-4, "-0.0001"), + (-1e-5, "-0.00001"), + (-1e-6, "-0.000001"), + (-1e-7, "-0.0000001"), + (-1e-8, "-0.00000001"), + (-1e-9, "-0.000000001"), + (-1e-10, "-0.0000000001"), + (-1e-11, "-0.00000000001"), + (-1e-12, "-0.000000000001"), + (-1e-13, "-0.0000000000001"), + (-1e-14, "-0.00000000000001"), + (-1e-15, "-0.000000000000001"), + (-1e-16, "-0.0000000000000001"), + (-1e-17, "-0.00000000000000001"), + (-1e-18, "-0.000000000000000001"), + (-1e-19, "-0.0000000000000000001"), + (-1e-20, "-0.00000000000000000001"), + (-1e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"), + (-1e-317, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"), + (-2.0, "-2"), + (-2e+1, "-20"), + (-2e+2, "-200"), + (-2e+3, "-2000"), + (-2e+4, "-20000"), + (-2e+5, "-200000"), + (-2e+6, "-2000000"), + (-2e+7, "-20000000"), + (-2e+8, "-200000000"), + (-2e+9, "-2000000000"), + (-2e+10, "-20000000000"), + (-2e+11, "-200000000000"), + (-2e+12, "-2000000000000"), + (-2e+13, "-20000000000000"), + (-2e+14, "-200000000000000"), + (-2e+15, "-2000000000000000"), + (-2e+16, "-20000000000000000"), + (-2e+17, "-200000000000000000"), + (-2e+18, "-2000000000000000000"), + (-2e+19, "-20000000000000000000"), + (-2e+20, "-200000000000000000000"), + (-2e+100, "-20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-2e+307, + "-20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-2e-1, "-0.2"), + (-2e-2, "-0.02"), + (-2e-3, "-0.002"), + (-2e-4, "-0.0002"), + (-2e-5, "-0.00002"), + (-2e-6, "-0.000002"), + (-2e-7, "-0.0000002"), + (-2e-8, "-0.00000002"), + (-2e-9, "-0.000000002"), + (-2e-10, "-0.0000000002"), + (-2e-11, "-0.00000000002"), + (-2e-12, "-0.000000000002"), + (-2e-13, "-0.0000000000002"), + (-2e-14, "-0.00000000000002"), + (-2e-15, "-0.000000000000002"), + (-2e-16, "-0.0000000000000002"), + (-2e-17, "-0.00000000000000002"), + (-2e-18, "-0.000000000000000002"), + (-2e-19, "-0.0000000000000000002"), + (-2e-20, "-0.00000000000000000002"), + (-2e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"), + (-2e-320, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"), + (-3.0, "-3"), + (-3e+1, "-30"), + (-3e+2, "-300"), + (-3e+3, "-3000"), + (-3e+4, "-30000"), + (-3e+5, "-300000"), + (-3e+6, "-3000000"), + (-3e+7, "-30000000"), + (-3e+8, "-300000000"), + (-3e+9, "-3000000000"), + (-3e+10, "-30000000000"), + (-3e+11, "-300000000000"), + (-3e+12, "-3000000000000"), + (-3e+13, "-30000000000000"), + (-3e+14, "-300000000000000"), + (-3e+15, "-3000000000000000"), + (-3e+16, "-30000000000000000"), + (-3e+17, "-300000000000000000"), + (-3e+18, "-3000000000000000000"), + (-3e+19, "-30000000000000000000"), + (-3e+20, "-300000000000000000000"), + (-3e+100, "-30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-3e+307, + "-30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-3e-1, "-0.3"), + (-3e-2, "-0.03"), + (-3e-3, "-0.003"), + (-3e-4, "-0.0003"), + (-3e-5, "-0.00003"), + (-3e-6, "-0.000003"), + (-3e-7, "-0.0000003"), + (-3e-8, "-0.00000003"), + (-3e-9, "-0.000000003"), + (-3e-10, "-0.0000000003"), + (-3e-11, "-0.00000000003"), + (-3e-12, "-0.000000000003"), + (-3e-13, "-0.0000000000003"), + (-3e-14, "-0.00000000000003"), + (-3e-15, "-0.000000000000003"), + (-3e-16, "-0.0000000000000003"), + (-3e-17, "-0.00000000000000003"), + (-3e-18, "-0.000000000000000003"), + (-3e-19, "-0.0000000000000000003"), + (-3e-20, "-0.00000000000000000003"), + (-3e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), + (-3e-320, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003"), + (-4.0, "-4"), + (-4e+1, "-40"), + (-4e+2, "-400"), + (-4e+3, "-4000"), + (-4e+4, "-40000"), + (-4e+5, "-400000"), + (-4e+6, "-4000000"), + (-4e+7, "-40000000"), + (-4e+8, "-400000000"), + (-4e+9, "-4000000000"), + (-4e+10, "-40000000000"), + (-4e+11, "-400000000000"), + (-4e+12, "-4000000000000"), + (-4e+13, "-40000000000000"), + (-4e+14, "-400000000000000"), + (-4e+15, "-4000000000000000"), + (-4e+16, "-40000000000000000"), + (-4e+17, "-400000000000000000"), + (-4e+18, "-4000000000000000000"), + (-4e+19, "-40000000000000000000"), + (-4e+20, "-400000000000000000000"), + (-4e+100, "-40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-4e+307, + "-40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-4e-1, "-0.4"), + (-4e-2, "-0.04"), + (-4e-3, "-0.004"), + (-4e-4, "-0.0004"), + (-4e-5, "-0.00004"), + (-4e-6, "-0.000004"), + (-4e-7, "-0.0000004"), + (-4e-8, "-0.00000004"), + (-4e-9, "-0.000000004"), + (-4e-10, "-0.0000000004"), + (-4e-11, "-0.00000000004"), + (-4e-12, "-0.000000000004"), + (-4e-13, "-0.0000000000004"), + (-4e-14, "-0.00000000000004"), + (-4e-15, "-0.000000000000004"), + (-4e-16, "-0.0000000000000004"), + (-4e-17, "-0.00000000000000004"), + (-4e-18, "-0.000000000000000004"), + (-4e-19, "-0.0000000000000000004"), + (-4e-20, "-0.00000000000000000004"), + (-4e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"), + (-4e-320, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004"), + (-5.0, "-5"), + (-5e+1, "-50"), + (-5e+2, "-500"), + (-5e+3, "-5000"), + (-5e+4, "-50000"), + (-5e+5, "-500000"), + (-5e+6, "-5000000"), + (-5e+7, "-50000000"), + (-5e+8, "-500000000"), + (-5e+9, "-5000000000"), + (-5e+10, "-50000000000"), + (-5e+11, "-500000000000"), + (-5e+12, "-5000000000000"), + (-5e+13, "-50000000000000"), + (-5e+14, "-500000000000000"), + (-5e+15, "-5000000000000000"), + (-5e+16, "-50000000000000000"), + (-5e+17, "-500000000000000000"), + (-5e+18, "-5000000000000000000"), + (-5e+19, "-50000000000000000000"), + (-5e+20, "-500000000000000000000"), + (-5e+100, "-50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-5e+307, + "-50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-5e-1, "-0.5"), + (-5e-2, "-0.05"), + (-5e-3, "-0.005"), + (-5e-4, "-0.0005"), + (-5e-5, "-0.00005"), + (-5e-6, "-0.000005"), + (-5e-7, "-0.0000005"), + (-5e-8, "-0.00000005"), + (-5e-9, "-0.000000005"), + (-5e-10, "-0.0000000005"), + (-5e-11, "-0.00000000005"), + (-5e-12, "-0.000000000005"), + (-5e-13, "-0.0000000000005"), + (-5e-14, "-0.00000000000005"), + (-5e-15, "-0.000000000000005"), + (-5e-16, "-0.0000000000000005"), + (-5e-17, "-0.00000000000000005"), + (-5e-18, "-0.000000000000000005"), + (-5e-19, "-0.0000000000000000005"), + (-5e-20, "-0.00000000000000000005"), + (-5e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005"), + (-5e-320, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005"), + (-6.0, "-6"), + (-6e+1, "-60"), + (-6e+2, "-600"), + (-6e+3, "-6000"), + (-6e+4, "-60000"), + (-6e+5, "-600000"), + (-6e+6, "-6000000"), + (-6e+7, "-60000000"), + (-6e+8, "-600000000"), + (-6e+9, "-6000000000"), + (-6e+10, "-60000000000"), + (-6e+11, "-600000000000"), + (-6e+12, "-6000000000000"), + (-6e+13, "-60000000000000"), + (-6e+14, "-600000000000000"), + (-6e+15, "-6000000000000000"), + (-6e+16, "-60000000000000000"), + (-6e+17, "-600000000000000000"), + (-6e+18, "-6000000000000000000"), + (-6e+19, "-60000000000000000000"), + (-6e+20, "-600000000000000000000"), + (-6e+100, "-60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-6e+307, + "-60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-6e-1, "-0.6"), + (-6e-2, "-0.06"), + (-6e-3, "-0.006"), + (-6e-4, "-0.0006"), + (-6e-5, "-0.00006"), + (-6e-6, "-0.000006"), + (-6e-7, "-0.0000006"), + (-6e-8, "-0.00000006"), + (-6e-9, "-0.000000006"), + (-6e-10, "-0.0000000006"), + (-6e-11, "-0.00000000006"), + (-6e-12, "-0.000000000006"), + (-6e-13, "-0.0000000000006"), + (-6e-14, "-0.00000000000006"), + (-6e-15, "-0.000000000000006"), + (-6e-16, "-0.0000000000000006"), + (-6e-17, "-0.00000000000000006"), + (-6e-18, "-0.000000000000000006"), + (-6e-19, "-0.0000000000000000006"), + (-6e-20, "-0.00000000000000000006"), + (-6e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006"), + (-6e-320, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006"), + (-7.0, "-7"), + (-7e+1, "-70"), + (-7e+2, "-700"), + (-7e+3, "-7000"), + (-7e+4, "-70000"), + (-7e+5, "-700000"), + (-7e+6, "-7000000"), + (-7e+7, "-70000000"), + (-7e+8, "-700000000"), + (-7e+9, "-7000000000"), + (-7e+10, "-70000000000"), + (-7e+11, "-700000000000"), + (-7e+12, "-7000000000000"), + (-7e+13, "-70000000000000"), + (-7e+14, "-700000000000000"), + (-7e+15, "-7000000000000000"), + (-7e+16, "-70000000000000000"), + (-7e+17, "-700000000000000000"), + (-7e+18, "-7000000000000000000"), + (-7e+19, "-70000000000000000000"), + (-7e+20, "-700000000000000000000"), + (-7e+100, "-70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-7e+307, + "-70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-7e-1, "-0.7"), + (-7e-2, "-0.07"), + (-7e-3, "-0.007"), + (-7e-4, "-0.0007"), + (-7e-5, "-0.00007"), + (-7e-6, "-0.000007"), + (-7e-7, "-0.0000007"), + (-7e-8, "-0.00000007"), + (-7e-9, "-0.000000007"), + (-7e-10, "-0.0000000007"), + (-7e-11, "-0.00000000007"), + (-7e-12, "-0.000000000007"), + (-7e-13, "-0.0000000000007"), + (-7e-14, "-0.00000000000007"), + (-7e-15, "-0.000000000000007"), + (-7e-16, "-0.0000000000000007"), + (-7e-17, "-0.00000000000000007"), + (-7e-18, "-0.000000000000000007"), + (-7e-19, "-0.0000000000000000007"), + (-7e-20, "-0.00000000000000000007"), + (-7e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007"), + (-7e-320, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007"), + (-8.0, "-8"), + (-8e+1, "-80"), + (-8e+2, "-800"), + (-8e+3, "-8000"), + (-8e+4, "-80000"), + (-8e+5, "-800000"), + (-8e+6, "-8000000"), + (-8e+7, "-80000000"), + (-8e+8, "-800000000"), + (-8e+9, "-8000000000"), + (-8e+10, "-80000000000"), + (-8e+11, "-800000000000"), + (-8e+12, "-8000000000000"), + (-8e+13, "-80000000000000"), + (-8e+14, "-800000000000000"), + (-8e+15, "-8000000000000000"), + (-8e+16, "-80000000000000000"), + (-8e+17, "-800000000000000000"), + (-8e+18, "-8000000000000000000"), + (-8e+19, "-80000000000000000000"), + (-8e+20, "-800000000000000000000"), + (-8e+100, "-80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-8e+307, + "-80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-8e-1, "-0.8"), + (-8e-2, "-0.08"), + (-8e-3, "-0.008"), + (-8e-4, "-0.0008"), + (-8e-5, "-0.00008"), + (-8e-6, "-0.000008"), + (-8e-7, "-0.0000008"), + (-8e-8, "-0.00000008"), + (-8e-9, "-0.000000008"), + (-8e-10, "-0.0000000008"), + (-8e-11, "-0.00000000008"), + (-8e-12, "-0.000000000008"), + (-8e-13, "-0.0000000000008"), + (-8e-14, "-0.00000000000008"), + (-8e-15, "-0.000000000000008"), + (-8e-16, "-0.0000000000000008"), + (-8e-17, "-0.00000000000000008"), + (-8e-18, "-0.000000000000000008"), + (-8e-19, "-0.0000000000000000008"), + (-8e-20, "-0.00000000000000000008"), + (-8e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008"), + (-8e-320, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008"), + (-9.0, "-9"), + (-9e+1, "-90"), + (-9e+2, "-900"), + (-9e+3, "-9000"), + (-9e+4, "-90000"), + (-9e+5, "-900000"), + (-9e+6, "-9000000"), + (-9e+7, "-90000000"), + (-9e+8, "-900000000"), + (-9e+9, "-9000000000"), + (-9e+10, "-90000000000"), + (-9e+11, "-900000000000"), + (-9e+12, "-9000000000000"), + (-9e+13, "-90000000000000"), + (-9e+14, "-900000000000000"), + (-9e+15, "-9000000000000000"), + (-9e+16, "-90000000000000000"), + (-9e+17, "-900000000000000000"), + (-9e+18, "-9000000000000000000"), + (-9e+19, "-90000000000000000000"), + (-9e+20, "-900000000000000000000"), + (-9e+100, "-90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-9e+307, + "-90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"), + (-9e-1, "-0.9"), + (-9e-2, "-0.09"), + (-9e-3, "-0.009"), + (-9e-4, "-0.0009"), + (-9e-5, "-0.00009"), + (-9e-6, "-0.000009"), + (-9e-7, "-0.0000009"), + (-9e-8, "-0.00000009"), + (-9e-9, "-0.000000009"), + (-9e-10, "-0.0000000009"), + (-9e-11, "-0.00000000009"), + (-9e-12, "-0.000000000009"), + (-9e-13, "-0.0000000000009"), + (-9e-14, "-0.00000000000009"), + (-9e-15, "-0.000000000000009"), + (-9e-16, "-0.0000000000000009"), + (-9e-17, "-0.00000000000000009"), + (-9e-18, "-0.000000000000000009"), + (-9e-19, "-0.0000000000000000009"), + (-9e-20, "-0.00000000000000000009"), + (-9e-100, "-0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"), + (-9e-320, + "-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"), + (1234567890123456.0, "1234567890123456"), + (123456789012345.6, "123456789012345.6"), + (12345678901234.56, "12345678901234.56"), + (1234567890123.456, "1234567890123.456"), + (123456789012.3456, "123456789012.3456"), + (12345678901.23456, "12345678901.23456"), + (1234567890.123456, "1234567890.123456"), + (123456789.0123456, "123456789.0123456"), + (12345678.90123456, "12345678.90123456"), + (1234567.890123456, "1234567.890123456"), + (123456.7890123456, "123456.7890123456"), + (12345.67890123456, "12345.67890123456"), + (1234.567890123456, "1234.567890123456"), + (123.4567890123456, "123.4567890123456"), + (12.34567890123456, "12.34567890123456"), + (1.234567890123456, "1.234567890123456"), + (-1234567890123456.0, "-1234567890123456"), + (-123456789012345.6, "-123456789012345.6"), + (-12345678901234.56, "-12345678901234.56"), + (-1234567890123.456, "-1234567890123.456"), + (-123456789012.3456, "-123456789012.3456"), + (-12345678901.23456, "-12345678901.23456"), + (-1234567890.123456, "-1234567890.123456"), + (-123456789.0123456, "-123456789.0123456"), + (-12345678.90123456, "-12345678.90123456"), + (-1234567.890123456, "-1234567.890123456"), + (-123456.7890123456, "-123456.7890123456"), + (-12345.67890123456, "-12345.67890123456"), + (-1234.567890123456, "-1234.567890123456"), + (-123.4567890123456, "-123.4567890123456"), + (-12.34567890123456, "-12.34567890123456"), + (-1.234567890123456, "-1.234567890123456"), + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach ((double value, string expected) in Data) yield return [value, expected]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalIsDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalIsDataAttribute.cs new file mode 100644 index 0000000..4fc0778 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalIsDataAttribute.cs @@ -0,0 +1,33 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalIsDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal value in TestDataGenerator.GenerateConstantValues()) + yield return [value, Guid.NewGuid()]; + + foreach (decimal value in TestDataGenerator.GenerateScaledValues()) + yield return [value, Guid.NewGuid()]; + + foreach (decimal value in TestDataGenerator.GenerateRandomValues()) + yield return [value, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/BigDecimalWriteDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/BigDecimalWriteDataAttribute.cs new file mode 100644 index 0000000..c7b6849 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/BigDecimalWriteDataAttribute.cs @@ -0,0 +1,27 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class BigDecimalWriteDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal value in TestDataGenerator.GenerateRandomValues()) + yield return [value]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/NumberFormatDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/NumberFormatDataAttribute.cs new file mode 100644 index 0000000..5d34aec --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/NumberFormatDataAttribute.cs @@ -0,0 +1,37 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class NumberFormatDataAttribute : DataAttribute +{ + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (CultureInfo culture in TestDataGenerator.GenerateCultures()) + { + foreach (decimal value in TestDataGenerator.GenerateStaticValues()) + yield return [value, culture, Guid.NewGuid()]; + + foreach (decimal value in TestDataGenerator.GenerateScaledValues()) + yield return [value, culture, Guid.NewGuid()]; + + foreach (decimal value in TestDataGenerator.GenerateRandomValues()) + yield return [value, culture, Guid.NewGuid()]; + } + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/NumberInfoEqualityComparerDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/NumberInfoEqualityComparerDataAttribute.cs new file mode 100644 index 0000000..e1d8280 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/NumberInfoEqualityComparerDataAttribute.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class NumberInfoEqualityComparerDataAttribute : DataAttribute +{ + private static readonly int[] Values = [0, 123456000, -123456000]; + private static readonly int[] Scales = [0, 1, 2, 3, 10]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal left in TestDataGenerator.GenerateScaledValues(Values, Scales)) + foreach (decimal right in TestDataGenerator.GenerateScaledValues(Values, Scales)) + yield return [left, right, Guid.NewGuid()]; + + foreach (decimal left in TestDataGenerator.GenerateRandomValues(count: 10)) + foreach (decimal right in TestDataGenerator.GenerateRandomValues(count: 10)) + yield return [left, right, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/NumberInfoOrdinalityComparerDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/NumberInfoOrdinalityComparerDataAttribute.cs new file mode 100644 index 0000000..851ab30 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/NumberInfoOrdinalityComparerDataAttribute.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class NumberInfoOrdinalityComparerDataAttribute : DataAttribute +{ + private static readonly int[] Values = [0, 123456000, -123456000]; + private static readonly int[] Scales = [0, 1, 2, 3, 10]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach (decimal left in TestDataGenerator.GenerateScaledValues(Values, Scales)) + foreach (decimal right in TestDataGenerator.GenerateScaledValues(Values, Scales)) + yield return [left, right, Guid.NewGuid()]; + + foreach (decimal left in TestDataGenerator.GenerateRandomValues(count: 10)) + foreach (decimal right in TestDataGenerator.GenerateRandomValues(count: 10)) + yield return [left, right, Guid.NewGuid()]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToDecimalDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToDecimalDataAttribute.cs new file mode 100644 index 0000000..7b663d3 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToDecimalDataAttribute.cs @@ -0,0 +1,466 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class NumericsExtensionsToDecimalDataAttribute : DataAttribute +{ + private static readonly (Int128 Value, int Scale, ScaleMode Mode, string Expected)[] Data = + [ + (0, 0, ScaleMode.Integral, "0"), + (0, 1, ScaleMode.Integral, "0.0"), + (0, 2, ScaleMode.Integral, "0.00"), + (0, 3, ScaleMode.Integral, "0.000"), + (0, 4, ScaleMode.Integral, "0.0000"), + (0, 5, ScaleMode.Integral, "0.00000"), + (0, 6, ScaleMode.Integral, "0.000000"), + (0, 7, ScaleMode.Integral, "0.0000000"), + (0, 8, ScaleMode.Integral, "0.00000000"), + (0, 9, ScaleMode.Integral, "0.000000000"), + (0, 10, ScaleMode.Integral, "0.0000000000"), + (0, 28, ScaleMode.Integral, "0.0000000000000000000000000000"), + (1, 0, ScaleMode.Integral, "1"), + (1, 1, ScaleMode.Integral, "1.0"), + (1, 2, ScaleMode.Integral, "1.00"), + (1, 3, ScaleMode.Integral, "1.000"), + (1, 4, ScaleMode.Integral, "1.0000"), + (1, 5, ScaleMode.Integral, "1.00000"), + (1, 6, ScaleMode.Integral, "1.000000"), + (1, 7, ScaleMode.Integral, "1.0000000"), + (1, 8, ScaleMode.Integral, "1.00000000"), + (1, 9, ScaleMode.Integral, "1.000000000"), + (1, 10, ScaleMode.Integral, "1.0000000000"), + (1, 28, ScaleMode.Integral, "1.0000000000000000000000000000"), + (-1, 0, ScaleMode.Integral, "-1"), + (-1, 1, ScaleMode.Integral, "-1.0"), + (-1, 2, ScaleMode.Integral, "-1.00"), + (-1, 3, ScaleMode.Integral, "-1.000"), + (-1, 4, ScaleMode.Integral, "-1.0000"), + (-1, 5, ScaleMode.Integral, "-1.00000"), + (-1, 6, ScaleMode.Integral, "-1.000000"), + (-1, 7, ScaleMode.Integral, "-1.0000000"), + (-1, 8, ScaleMode.Integral, "-1.00000000"), + (-1, 9, ScaleMode.Integral, "-1.000000000"), + (-1, 10, ScaleMode.Integral, "-1.0000000000"), + (-1, 28, ScaleMode.Integral, "-1.0000000000000000000000000000"), + (0, 0, ScaleMode.Fractional, "0"), + (0, 1, ScaleMode.Fractional, "0.0"), + (0, 2, ScaleMode.Fractional, "0.00"), + (0, 3, ScaleMode.Fractional, "0.000"), + (0, 4, ScaleMode.Fractional, "0.0000"), + (0, 5, ScaleMode.Fractional, "0.00000"), + (0, 6, ScaleMode.Fractional, "0.000000"), + (0, 7, ScaleMode.Fractional, "0.0000000"), + (0, 8, ScaleMode.Fractional, "0.00000000"), + (0, 9, ScaleMode.Fractional, "0.000000000"), + (0, 10, ScaleMode.Fractional, "0.0000000000"), + (0, 28, ScaleMode.Fractional, "0.0000000000000000000000000000"), + (1, 0, ScaleMode.Fractional, "1"), + (1, 1, ScaleMode.Fractional, "0.1"), + (1, 2, ScaleMode.Fractional, "0.01"), + (1, 3, ScaleMode.Fractional, "0.001"), + (1, 4, ScaleMode.Fractional, "0.0001"), + (1, 5, ScaleMode.Fractional, "0.00001"), + (1, 6, ScaleMode.Fractional, "0.000001"), + (1, 7, ScaleMode.Fractional, "0.0000001"), + (1, 8, ScaleMode.Fractional, "0.00000001"), + (1, 9, ScaleMode.Fractional, "0.000000001"), + (1, 10, ScaleMode.Fractional, "0.0000000001"), + (1, 28, ScaleMode.Fractional, "0.0000000000000000000000000001"), + (-1, 0, ScaleMode.Fractional, "-1"), + (-1, 1, ScaleMode.Fractional, "-0.1"), + (-1, 2, ScaleMode.Fractional, "-0.01"), + (-1, 3, ScaleMode.Fractional, "-0.001"), + (-1, 4, ScaleMode.Fractional, "-0.0001"), + (-1, 5, ScaleMode.Fractional, "-0.00001"), + (-1, 6, ScaleMode.Fractional, "-0.000001"), + (-1, 7, ScaleMode.Fractional, "-0.0000001"), + (-1, 8, ScaleMode.Fractional, "-0.00000001"), + (-1, 9, ScaleMode.Fractional, "-0.000000001"), + (-1, 28, ScaleMode.Fractional, "-0.0000000000000000000000000001"), + (sbyte.MinValue, 0, ScaleMode.Integral, "-128"), + (sbyte.MinValue, 1, ScaleMode.Integral, "-128.0"), + (sbyte.MinValue, 2, ScaleMode.Integral, "-128.00"), + (sbyte.MinValue, 3, ScaleMode.Integral, "-128.000"), + (sbyte.MinValue, 4, ScaleMode.Integral, "-128.0000"), + (sbyte.MinValue, 5, ScaleMode.Integral, "-128.00000"), + (sbyte.MinValue, 6, ScaleMode.Integral, "-128.000000"), + (sbyte.MinValue, 7, ScaleMode.Integral, "-128.0000000"), + (sbyte.MinValue, 8, ScaleMode.Integral, "-128.00000000"), + (sbyte.MinValue, 9, ScaleMode.Integral, "-128.000000000"), + (sbyte.MinValue, 10, ScaleMode.Integral, "-128.0000000000"), + (sbyte.MaxValue, 0, ScaleMode.Integral, "127"), + (sbyte.MaxValue, 1, ScaleMode.Integral, "127.0"), + (sbyte.MaxValue, 2, ScaleMode.Integral, "127.00"), + (sbyte.MaxValue, 3, ScaleMode.Integral, "127.000"), + (sbyte.MaxValue, 4, ScaleMode.Integral, "127.0000"), + (sbyte.MaxValue, 5, ScaleMode.Integral, "127.00000"), + (sbyte.MaxValue, 6, ScaleMode.Integral, "127.000000"), + (sbyte.MaxValue, 7, ScaleMode.Integral, "127.0000000"), + (sbyte.MaxValue, 8, ScaleMode.Integral, "127.00000000"), + (sbyte.MaxValue, 9, ScaleMode.Integral, "127.000000000"), + (sbyte.MaxValue, 10, ScaleMode.Integral, "127.0000000000"), + (sbyte.MinValue, 0, ScaleMode.Fractional, "-128"), + (sbyte.MinValue, 1, ScaleMode.Fractional, "-12.8"), + (sbyte.MinValue, 2, ScaleMode.Fractional, "-1.28"), + (sbyte.MinValue, 3, ScaleMode.Fractional, "-0.128"), + (sbyte.MinValue, 4, ScaleMode.Fractional, "-0.0128"), + (sbyte.MinValue, 5, ScaleMode.Fractional, "-0.00128"), + (sbyte.MinValue, 6, ScaleMode.Fractional, "-0.000128"), + (sbyte.MinValue, 7, ScaleMode.Fractional, "-0.0000128"), + (sbyte.MinValue, 8, ScaleMode.Fractional, "-0.00000128"), + (sbyte.MinValue, 9, ScaleMode.Fractional, "-0.000000128"), + (sbyte.MinValue, 10, ScaleMode.Fractional, "-0.0000000128"), + (sbyte.MinValue, 28, ScaleMode.Fractional, "-0.0000000000000000000000000128"), + (sbyte.MaxValue, 0, ScaleMode.Fractional, "127"), + (sbyte.MaxValue, 1, ScaleMode.Fractional, "12.7"), + (sbyte.MaxValue, 2, ScaleMode.Fractional, "1.27"), + (sbyte.MaxValue, 3, ScaleMode.Fractional, "0.127"), + (sbyte.MaxValue, 4, ScaleMode.Fractional, "0.0127"), + (sbyte.MaxValue, 5, ScaleMode.Fractional, "0.00127"), + (sbyte.MaxValue, 6, ScaleMode.Fractional, "0.000127"), + (sbyte.MaxValue, 7, ScaleMode.Fractional, "0.0000127"), + (sbyte.MaxValue, 8, ScaleMode.Fractional, "0.00000127"), + (sbyte.MaxValue, 9, ScaleMode.Fractional, "0.000000127"), + (sbyte.MaxValue, 10, ScaleMode.Fractional, "0.0000000127"), + (sbyte.MaxValue, 28, ScaleMode.Fractional, "0.0000000000000000000000000127"), + (byte.MinValue, 0, ScaleMode.Integral, "0"), + (byte.MinValue, 1, ScaleMode.Integral, "0.0"), + (byte.MinValue, 2, ScaleMode.Integral, "0.00"), + (byte.MinValue, 3, ScaleMode.Integral, "0.000"), + (byte.MinValue, 4, ScaleMode.Integral, "0.0000"), + (byte.MinValue, 5, ScaleMode.Integral, "0.00000"), + (byte.MinValue, 6, ScaleMode.Integral, "0.000000"), + (byte.MinValue, 7, ScaleMode.Integral, "0.0000000"), + (byte.MinValue, 8, ScaleMode.Integral, "0.00000000"), + (byte.MinValue, 9, ScaleMode.Integral, "0.000000000"), + (byte.MinValue, 10, ScaleMode.Integral, "0.0000000000"), + (byte.MinValue, 28, ScaleMode.Integral, "0.0000000000000000000000000000"), + (byte.MaxValue, 0, ScaleMode.Integral, "255"), + (byte.MaxValue, 1, ScaleMode.Integral, "255.0"), + (byte.MaxValue, 2, ScaleMode.Integral, "255.00"), + (byte.MaxValue, 3, ScaleMode.Integral, "255.000"), + (byte.MaxValue, 4, ScaleMode.Integral, "255.0000"), + (byte.MaxValue, 5, ScaleMode.Integral, "255.00000"), + (byte.MaxValue, 6, ScaleMode.Integral, "255.000000"), + (byte.MaxValue, 7, ScaleMode.Integral, "255.0000000"), + (byte.MaxValue, 8, ScaleMode.Integral, "255.00000000"), + (byte.MaxValue, 9, ScaleMode.Integral, "255.000000000"), + (byte.MaxValue, 10, ScaleMode.Integral, "255.0000000000"), + (byte.MinValue, 0, ScaleMode.Fractional, "0"), + (byte.MinValue, 1, ScaleMode.Fractional, "0.0"), + (byte.MinValue, 2, ScaleMode.Fractional, "0.00"), + (byte.MinValue, 3, ScaleMode.Fractional, "0.000"), + (byte.MinValue, 4, ScaleMode.Fractional, "0.0000"), + (byte.MinValue, 5, ScaleMode.Fractional, "0.00000"), + (byte.MinValue, 6, ScaleMode.Fractional, "0.000000"), + (byte.MinValue, 7, ScaleMode.Fractional, "0.0000000"), + (byte.MinValue, 8, ScaleMode.Fractional, "0.00000000"), + (byte.MinValue, 9, ScaleMode.Fractional, "0.000000000"), + (byte.MinValue, 10, ScaleMode.Fractional, "0.0000000000"), + (byte.MinValue, 28, ScaleMode.Fractional, "0.0000000000000000000000000000"), + (byte.MaxValue, 0, ScaleMode.Fractional, "255"), + (byte.MaxValue, 1, ScaleMode.Fractional, "25.5"), + (byte.MaxValue, 2, ScaleMode.Fractional, "2.55"), + (byte.MaxValue, 3, ScaleMode.Fractional, "0.255"), + (byte.MaxValue, 4, ScaleMode.Fractional, "0.0255"), + (byte.MaxValue, 5, ScaleMode.Fractional, "0.00255"), + (byte.MaxValue, 6, ScaleMode.Fractional, "0.000255"), + (byte.MaxValue, 7, ScaleMode.Fractional, "0.0000255"), + (byte.MaxValue, 8, ScaleMode.Fractional, "0.00000255"), + (byte.MaxValue, 9, ScaleMode.Fractional, "0.000000255"), + (byte.MaxValue, 10, ScaleMode.Fractional, "0.0000000255"), + (byte.MaxValue, 28, ScaleMode.Fractional, "0.0000000000000000000000000255"), + (short.MinValue, 0, ScaleMode.Integral, "-32768"), + (short.MinValue, 1, ScaleMode.Integral, "-32768.0"), + (short.MinValue, 2, ScaleMode.Integral, "-32768.00"), + (short.MinValue, 3, ScaleMode.Integral, "-32768.000"), + (short.MinValue, 4, ScaleMode.Integral, "-32768.0000"), + (short.MinValue, 5, ScaleMode.Integral, "-32768.00000"), + (short.MinValue, 6, ScaleMode.Integral, "-32768.000000"), + (short.MinValue, 7, ScaleMode.Integral, "-32768.0000000"), + (short.MinValue, 8, ScaleMode.Integral, "-32768.00000000"), + (short.MinValue, 9, ScaleMode.Integral, "-32768.000000000"), + (short.MinValue, 10, ScaleMode.Integral, "-32768.0000000000"), + (short.MaxValue, 0, ScaleMode.Integral, "32767"), + (short.MaxValue, 1, ScaleMode.Integral, "32767.0"), + (short.MaxValue, 2, ScaleMode.Integral, "32767.00"), + (short.MaxValue, 3, ScaleMode.Integral, "32767.000"), + (short.MaxValue, 4, ScaleMode.Integral, "32767.0000"), + (short.MaxValue, 5, ScaleMode.Integral, "32767.00000"), + (short.MaxValue, 6, ScaleMode.Integral, "32767.000000"), + (short.MaxValue, 7, ScaleMode.Integral, "32767.0000000"), + (short.MaxValue, 8, ScaleMode.Integral, "32767.00000000"), + (short.MaxValue, 9, ScaleMode.Integral, "32767.000000000"), + (short.MaxValue, 10, ScaleMode.Integral, "32767.0000000000"), + (short.MinValue, 0, ScaleMode.Fractional, "-32768"), + (short.MinValue, 1, ScaleMode.Fractional, "-3276.8"), + (short.MinValue, 2, ScaleMode.Fractional, "-327.68"), + (short.MinValue, 3, ScaleMode.Fractional, "-32.768"), + (short.MinValue, 4, ScaleMode.Fractional, "-3.2768"), + (short.MinValue, 5, ScaleMode.Fractional, "-0.32768"), + (short.MinValue, 6, ScaleMode.Fractional, "-0.032768"), + (short.MinValue, 7, ScaleMode.Fractional, "-0.0032768"), + (short.MinValue, 8, ScaleMode.Fractional, "-0.00032768"), + (short.MinValue, 9, ScaleMode.Fractional, "-0.000032768"), + (short.MinValue, 10, ScaleMode.Fractional, "-0.0000032768"), + (short.MinValue, 28, ScaleMode.Fractional, "-0.0000000000000000000000032768"), + (short.MaxValue, 0, ScaleMode.Fractional, "32767"), + (short.MaxValue, 1, ScaleMode.Fractional, "3276.7"), + (short.MaxValue, 2, ScaleMode.Fractional, "327.67"), + (short.MaxValue, 3, ScaleMode.Fractional, "32.767"), + (short.MaxValue, 4, ScaleMode.Fractional, "3.2767"), + (short.MaxValue, 5, ScaleMode.Fractional, "0.32767"), + (short.MaxValue, 6, ScaleMode.Fractional, "0.032767"), + (short.MaxValue, 7, ScaleMode.Fractional, "0.0032767"), + (short.MaxValue, 8, ScaleMode.Fractional, "0.00032767"), + (short.MaxValue, 9, ScaleMode.Fractional, "0.000032767"), + (short.MaxValue, 10, ScaleMode.Fractional, "0.0000032767"), + (short.MaxValue, 28, ScaleMode.Fractional, "0.0000000000000000000000032767"), + (ushort.MinValue, 0, ScaleMode.Integral, "0"), + (ushort.MinValue, 1, ScaleMode.Integral, "0.0"), + (ushort.MinValue, 2, ScaleMode.Integral, "0.00"), + (ushort.MinValue, 3, ScaleMode.Integral, "0.000"), + (ushort.MinValue, 4, ScaleMode.Integral, "0.0000"), + (ushort.MinValue, 5, ScaleMode.Integral, "0.00000"), + (ushort.MinValue, 6, ScaleMode.Integral, "0.000000"), + (ushort.MinValue, 7, ScaleMode.Integral, "0.0000000"), + (ushort.MinValue, 8, ScaleMode.Integral, "0.00000000"), + (ushort.MinValue, 9, ScaleMode.Integral, "0.000000000"), + (ushort.MinValue, 10, ScaleMode.Integral, "0.0000000000"), + (ushort.MaxValue, 0, ScaleMode.Integral, "65535"), + (ushort.MaxValue, 1, ScaleMode.Integral, "65535.0"), + (ushort.MaxValue, 2, ScaleMode.Integral, "65535.00"), + (ushort.MaxValue, 3, ScaleMode.Integral, "65535.000"), + (ushort.MaxValue, 4, ScaleMode.Integral, "65535.0000"), + (ushort.MaxValue, 5, ScaleMode.Integral, "65535.00000"), + (ushort.MaxValue, 6, ScaleMode.Integral, "65535.000000"), + (ushort.MaxValue, 7, ScaleMode.Integral, "65535.0000000"), + (ushort.MaxValue, 8, ScaleMode.Integral, "65535.00000000"), + (ushort.MaxValue, 9, ScaleMode.Integral, "65535.000000000"), + (ushort.MaxValue, 10, ScaleMode.Integral, "65535.0000000000"), + (ushort.MinValue, 0, ScaleMode.Fractional, "0"), + (ushort.MinValue, 1, ScaleMode.Fractional, "0.0"), + (ushort.MinValue, 2, ScaleMode.Fractional, "0.00"), + (ushort.MinValue, 3, ScaleMode.Fractional, "0.000"), + (ushort.MinValue, 4, ScaleMode.Fractional, "0.0000"), + (ushort.MinValue, 5, ScaleMode.Fractional, "0.00000"), + (ushort.MinValue, 6, ScaleMode.Fractional, "0.000000"), + (ushort.MinValue, 7, ScaleMode.Fractional, "0.0000000"), + (ushort.MinValue, 8, ScaleMode.Fractional, "0.00000000"), + (ushort.MinValue, 9, ScaleMode.Fractional, "0.000000000"), + (ushort.MinValue, 10, ScaleMode.Fractional, "0.0000000000"), + (ushort.MinValue, 28, ScaleMode.Fractional, "0.0000000000000000000000000000"), + (ushort.MaxValue, 0, ScaleMode.Fractional, "65535"), + (ushort.MaxValue, 1, ScaleMode.Fractional, "6553.5"), + (ushort.MaxValue, 2, ScaleMode.Fractional, "655.35"), + (ushort.MaxValue, 3, ScaleMode.Fractional, "65.535"), + (ushort.MaxValue, 4, ScaleMode.Fractional, "6.5535"), + (ushort.MaxValue, 5, ScaleMode.Fractional, "0.65535"), + (ushort.MaxValue, 6, ScaleMode.Fractional, "0.065535"), + (ushort.MaxValue, 7, ScaleMode.Fractional, "0.0065535"), + (ushort.MaxValue, 8, ScaleMode.Fractional, "0.00065535"), + (ushort.MaxValue, 9, ScaleMode.Fractional, "0.000065535"), + (ushort.MaxValue, 10, ScaleMode.Fractional, "0.0000065535"), + (ushort.MaxValue, 28, ScaleMode.Fractional, "0.0000000000000000000000065535"), + (int.MinValue, 0, ScaleMode.Integral, "-2147483648"), + (int.MinValue, 1, ScaleMode.Integral, "-2147483648.0"), + (int.MinValue, 2, ScaleMode.Integral, "-2147483648.00"), + (int.MinValue, 3, ScaleMode.Integral, "-2147483648.000"), + (int.MinValue, 4, ScaleMode.Integral, "-2147483648.0000"), + (int.MinValue, 5, ScaleMode.Integral, "-2147483648.00000"), + (int.MinValue, 6, ScaleMode.Integral, "-2147483648.000000"), + (int.MinValue, 7, ScaleMode.Integral, "-2147483648.0000000"), + (int.MinValue, 8, ScaleMode.Integral, "-2147483648.00000000"), + (int.MinValue, 9, ScaleMode.Integral, "-2147483648.000000000"), + (int.MinValue, 10, ScaleMode.Integral, "-2147483648.0000000000"), + (int.MaxValue, 0, ScaleMode.Integral, "2147483647"), + (int.MaxValue, 1, ScaleMode.Integral, "2147483647.0"), + (int.MaxValue, 2, ScaleMode.Integral, "2147483647.00"), + (int.MaxValue, 3, ScaleMode.Integral, "2147483647.000"), + (int.MaxValue, 4, ScaleMode.Integral, "2147483647.0000"), + (int.MaxValue, 5, ScaleMode.Integral, "2147483647.00000"), + (int.MaxValue, 6, ScaleMode.Integral, "2147483647.000000"), + (int.MaxValue, 7, ScaleMode.Integral, "2147483647.0000000"), + (int.MaxValue, 8, ScaleMode.Integral, "2147483647.00000000"), + (int.MaxValue, 9, ScaleMode.Integral, "2147483647.000000000"), + (int.MaxValue, 10, ScaleMode.Integral, "2147483647.0000000000"), + (int.MinValue, 0, ScaleMode.Fractional, "-2147483648"), + (int.MinValue, 1, ScaleMode.Fractional, "-214748364.8"), + (int.MinValue, 2, ScaleMode.Fractional, "-21474836.48"), + (int.MinValue, 3, ScaleMode.Fractional, "-2147483.648"), + (int.MinValue, 4, ScaleMode.Fractional, "-214748.3648"), + (int.MinValue, 5, ScaleMode.Fractional, "-21474.83648"), + (int.MinValue, 6, ScaleMode.Fractional, "-2147.483648"), + (int.MinValue, 7, ScaleMode.Fractional, "-214.7483648"), + (int.MinValue, 8, ScaleMode.Fractional, "-21.47483648"), + (int.MinValue, 9, ScaleMode.Fractional, "-2.147483648"), + (int.MinValue, 10, ScaleMode.Fractional, "-0.2147483648"), + (int.MinValue, 28, ScaleMode.Fractional, "-0.0000000000000000002147483648"), + (int.MaxValue, 0, ScaleMode.Fractional, "2147483647"), + (int.MaxValue, 1, ScaleMode.Fractional, "214748364.7"), + (int.MaxValue, 2, ScaleMode.Fractional, "21474836.47"), + (int.MaxValue, 3, ScaleMode.Fractional, "2147483.647"), + (int.MaxValue, 4, ScaleMode.Fractional, "214748.3647"), + (int.MaxValue, 5, ScaleMode.Fractional, "21474.83647"), + (int.MaxValue, 6, ScaleMode.Fractional, "2147.483647"), + (int.MaxValue, 7, ScaleMode.Fractional, "214.7483647"), + (int.MaxValue, 8, ScaleMode.Fractional, "21.47483647"), + (int.MaxValue, 9, ScaleMode.Fractional, "2.147483647"), + (int.MaxValue, 10, ScaleMode.Fractional, "0.2147483647"), + (int.MaxValue, 28, ScaleMode.Fractional, "0.0000000000000000002147483647"), + (uint.MinValue, 0, ScaleMode.Integral, "0"), + (uint.MinValue, 1, ScaleMode.Integral, "0.0"), + (uint.MinValue, 2, ScaleMode.Integral, "0.00"), + (uint.MinValue, 3, ScaleMode.Integral, "0.000"), + (uint.MinValue, 4, ScaleMode.Integral, "0.0000"), + (uint.MinValue, 5, ScaleMode.Integral, "0.00000"), + (uint.MinValue, 6, ScaleMode.Integral, "0.000000"), + (uint.MinValue, 7, ScaleMode.Integral, "0.0000000"), + (uint.MinValue, 8, ScaleMode.Integral, "0.00000000"), + (uint.MinValue, 9, ScaleMode.Integral, "0.000000000"), + (uint.MinValue, 10, ScaleMode.Integral, "0.0000000000"), + (uint.MaxValue, 0, ScaleMode.Integral, "4294967295"), + (uint.MaxValue, 1, ScaleMode.Integral, "4294967295.0"), + (uint.MaxValue, 2, ScaleMode.Integral, "4294967295.00"), + (uint.MaxValue, 3, ScaleMode.Integral, "4294967295.000"), + (uint.MaxValue, 4, ScaleMode.Integral, "4294967295.0000"), + (uint.MaxValue, 5, ScaleMode.Integral, "4294967295.00000"), + (uint.MaxValue, 6, ScaleMode.Integral, "4294967295.000000"), + (uint.MaxValue, 7, ScaleMode.Integral, "4294967295.0000000"), + (uint.MaxValue, 8, ScaleMode.Integral, "4294967295.00000000"), + (uint.MaxValue, 9, ScaleMode.Integral, "4294967295.000000000"), + (uint.MaxValue, 10, ScaleMode.Integral, "4294967295.0000000000"), + (uint.MinValue, 0, ScaleMode.Fractional, "0"), + (uint.MinValue, 1, ScaleMode.Fractional, "0.0"), + (uint.MinValue, 2, ScaleMode.Fractional, "0.00"), + (uint.MinValue, 3, ScaleMode.Fractional, "0.000"), + (uint.MinValue, 4, ScaleMode.Fractional, "0.0000"), + (uint.MinValue, 5, ScaleMode.Fractional, "0.00000"), + (uint.MinValue, 6, ScaleMode.Fractional, "0.000000"), + (uint.MinValue, 7, ScaleMode.Fractional, "0.0000000"), + (uint.MinValue, 8, ScaleMode.Fractional, "0.00000000"), + (uint.MinValue, 9, ScaleMode.Fractional, "0.000000000"), + (uint.MinValue, 10, ScaleMode.Fractional, "0.0000000000"), + (uint.MinValue, 28, ScaleMode.Fractional, "0.0000000000000000000000000000"), + (uint.MaxValue, 0, ScaleMode.Fractional, "4294967295"), + (uint.MaxValue, 1, ScaleMode.Fractional, "429496729.5"), + (uint.MaxValue, 2, ScaleMode.Fractional, "42949672.95"), + (uint.MaxValue, 3, ScaleMode.Fractional, "4294967.295"), + (uint.MaxValue, 4, ScaleMode.Fractional, "429496.7295"), + (uint.MaxValue, 5, ScaleMode.Fractional, "42949.67295"), + (uint.MaxValue, 6, ScaleMode.Fractional, "4294.967295"), + (uint.MaxValue, 7, ScaleMode.Fractional, "429.4967295"), + (uint.MaxValue, 8, ScaleMode.Fractional, "42.94967295"), + (uint.MaxValue, 9, ScaleMode.Fractional, "4.294967295"), + (uint.MaxValue, 10, ScaleMode.Fractional, "0.4294967295"), + (uint.MaxValue, 28, ScaleMode.Fractional, "0.0000000000000000004294967295"), + (long.MinValue, 0, ScaleMode.Integral, "-9223372036854775808"), + (long.MinValue, 1, ScaleMode.Integral, "-9223372036854775808.0"), + (long.MinValue, 2, ScaleMode.Integral, "-9223372036854775808.00"), + (long.MinValue, 3, ScaleMode.Integral, "-9223372036854775808.000"), + (long.MinValue, 4, ScaleMode.Integral, "-9223372036854775808.0000"), + (long.MinValue, 5, ScaleMode.Integral, "-9223372036854775808.00000"), + (long.MinValue, 6, ScaleMode.Integral, "-9223372036854775808.000000"), + (long.MinValue, 7, ScaleMode.Integral, "-9223372036854775808.0000000"), + (long.MinValue, 8, ScaleMode.Integral, "-9223372036854775808.00000000"), + (long.MinValue, 9, ScaleMode.Integral, "-9223372036854775808.000000000"), + (long.MaxValue, 0, ScaleMode.Integral, "9223372036854775807"), + (long.MaxValue, 1, ScaleMode.Integral, "9223372036854775807.0"), + (long.MaxValue, 2, ScaleMode.Integral, "9223372036854775807.00"), + (long.MaxValue, 3, ScaleMode.Integral, "9223372036854775807.000"), + (long.MaxValue, 4, ScaleMode.Integral, "9223372036854775807.0000"), + (long.MaxValue, 5, ScaleMode.Integral, "9223372036854775807.00000"), + (long.MaxValue, 6, ScaleMode.Integral, "9223372036854775807.000000"), + (long.MaxValue, 7, ScaleMode.Integral, "9223372036854775807.0000000"), + (long.MaxValue, 8, ScaleMode.Integral, "9223372036854775807.00000000"), + (long.MaxValue, 9, ScaleMode.Integral, "9223372036854775807.000000000"), + (long.MinValue, 0, ScaleMode.Fractional, "-9223372036854775808"), + (long.MinValue, 1, ScaleMode.Fractional, "-922337203685477580.8"), + (long.MinValue, 2, ScaleMode.Fractional, "-92233720368547758.08"), + (long.MinValue, 3, ScaleMode.Fractional, "-9223372036854775.808"), + (long.MinValue, 4, ScaleMode.Fractional, "-922337203685477.5808"), + (long.MinValue, 5, ScaleMode.Fractional, "-92233720368547.75808"), + (long.MinValue, 6, ScaleMode.Fractional, "-9223372036854.775808"), + (long.MinValue, 7, ScaleMode.Fractional, "-922337203685.4775808"), + (long.MinValue, 8, ScaleMode.Fractional, "-92233720368.54775808"), + (long.MinValue, 9, ScaleMode.Fractional, "-9223372036.854775808"), + (long.MinValue, 10, ScaleMode.Fractional, "-922337203.6854775808"), + (long.MinValue, 28, ScaleMode.Fractional, "-0.0000000009223372036854775808"), + (long.MaxValue, 0, ScaleMode.Fractional, "9223372036854775807"), + (long.MaxValue, 1, ScaleMode.Fractional, "922337203685477580.7"), + (long.MaxValue, 2, ScaleMode.Fractional, "92233720368547758.07"), + (long.MaxValue, 3, ScaleMode.Fractional, "9223372036854775.807"), + (long.MaxValue, 4, ScaleMode.Fractional, "922337203685477.5807"), + (long.MaxValue, 5, ScaleMode.Fractional, "92233720368547.75807"), + (long.MaxValue, 6, ScaleMode.Fractional, "9223372036854.775807"), + (long.MaxValue, 7, ScaleMode.Fractional, "922337203685.4775807"), + (long.MaxValue, 8, ScaleMode.Fractional, "92233720368.54775807"), + (long.MaxValue, 9, ScaleMode.Fractional, "9223372036.854775807"), + (long.MaxValue, 10, ScaleMode.Fractional, "922337203.6854775807"), + (long.MaxValue, 28, ScaleMode.Fractional, "0.0000000009223372036854775807"), + (ulong.MinValue, 0, ScaleMode.Integral, "0"), + (ulong.MinValue, 1, ScaleMode.Integral, "0.0"), + (ulong.MinValue, 2, ScaleMode.Integral, "0.00"), + (ulong.MinValue, 3, ScaleMode.Integral, "0.000"), + (ulong.MinValue, 4, ScaleMode.Integral, "0.0000"), + (ulong.MinValue, 5, ScaleMode.Integral, "0.00000"), + (ulong.MinValue, 6, ScaleMode.Integral, "0.000000"), + (ulong.MinValue, 7, ScaleMode.Integral, "0.0000000"), + (ulong.MinValue, 8, ScaleMode.Integral, "0.00000000"), + (ulong.MinValue, 9, ScaleMode.Integral, "0.000000000"), + (ulong.MaxValue, 0, ScaleMode.Integral, "18446744073709551615"), + (ulong.MaxValue, 1, ScaleMode.Integral, "18446744073709551615.0"), + (ulong.MaxValue, 2, ScaleMode.Integral, "18446744073709551615.00"), + (ulong.MaxValue, 3, ScaleMode.Integral, "18446744073709551615.000"), + (ulong.MaxValue, 4, ScaleMode.Integral, "18446744073709551615.0000"), + (ulong.MaxValue, 5, ScaleMode.Integral, "18446744073709551615.00000"), + (ulong.MaxValue, 6, ScaleMode.Integral, "18446744073709551615.000000"), + (ulong.MaxValue, 7, ScaleMode.Integral, "18446744073709551615.0000000"), + (ulong.MaxValue, 8, ScaleMode.Integral, "18446744073709551615.00000000"), + (ulong.MaxValue, 9, ScaleMode.Integral, "18446744073709551615.000000000"), + (ulong.MinValue, 0, ScaleMode.Fractional, "0"), + (ulong.MinValue, 1, ScaleMode.Fractional, "0.0"), + (ulong.MinValue, 2, ScaleMode.Fractional, "0.00"), + (ulong.MinValue, 3, ScaleMode.Fractional, "0.000"), + (ulong.MinValue, 4, ScaleMode.Fractional, "0.0000"), + (ulong.MinValue, 5, ScaleMode.Fractional, "0.00000"), + (ulong.MinValue, 6, ScaleMode.Fractional, "0.000000"), + (ulong.MinValue, 7, ScaleMode.Fractional, "0.0000000"), + (ulong.MinValue, 8, ScaleMode.Fractional, "0.00000000"), + (ulong.MinValue, 9, ScaleMode.Fractional, "0.000000000"), + (ulong.MinValue, 10, ScaleMode.Fractional, "0.0000000000"), + (ulong.MinValue, 28, ScaleMode.Fractional, "0.0000000000000000000000000000"), + (ulong.MaxValue, 0, ScaleMode.Fractional, "18446744073709551615"), + (ulong.MaxValue, 1, ScaleMode.Fractional, "1844674407370955161.5"), + (ulong.MaxValue, 2, ScaleMode.Fractional, "184467440737095516.15"), + (ulong.MaxValue, 3, ScaleMode.Fractional, "18446744073709551.615"), + (ulong.MaxValue, 4, ScaleMode.Fractional, "1844674407370955.1615"), + (ulong.MaxValue, 5, ScaleMode.Fractional, "184467440737095.51615"), + (ulong.MaxValue, 6, ScaleMode.Fractional, "18446744073709.551615"), + (ulong.MaxValue, 7, ScaleMode.Fractional, "1844674407370.9551615"), + (ulong.MaxValue, 8, ScaleMode.Fractional, "184467440737.09551615"), + (ulong.MaxValue, 9, ScaleMode.Fractional, "18446744073.709551615"), + (ulong.MaxValue, 10, ScaleMode.Fractional, "1844674407.3709551615"), + (ulong.MaxValue, 28, ScaleMode.Fractional, "0.0000000018446744073709551615") + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach ((Int128 value, int scale, ScaleMode mode, string expected) in Data) yield return [value, scale, mode, expected]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoDecimalDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoDecimalDataAttribute.cs new file mode 100644 index 0000000..d1c4518 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoDecimalDataAttribute.cs @@ -0,0 +1,133 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class NumericsExtensionsToNumberInfoDecimalDataAttribute : DataAttribute +{ + private static readonly (decimal Value, BigInteger UnscaledValue, int Scale, BigInteger Significand, int Exponent, int Sign, int Precision)[] Data = + [ + (decimal.Zero, 0, 0, 0, 0, 0, 1), + (decimal.MaxValue, (BigInteger)79228162514264337593543950335m, 0, (BigInteger)79228162514264337593543950335m, 0, 1, 29), + (decimal.MinValue, (BigInteger)(-79228162514264337593543950335m), 0, (BigInteger)(-79228162514264337593543950335m), 0, -1, 29), + (1.0m, 10, 1, 1, 0, 1, 2), + (1.00m, 100, 2, 1, 0, 1, 3), + (1.000m, 1000, 3, 1, 0, 1, 4), + (1.0000m, 10000, 4, 1, 0, 1, 5), + (1.00000m, 100000, 5, 1, 0, 1, 6), + (1.000000m, 1000000, 6, 1, 0, 1, 7), + (1.0000000m, 10000000, 7, 1, 0, 1, 8), + (1.00000000m, 100000000, 8, 1, 0, 1, 9), + (1.000000000m, 1000000000, 9, 1, 0, 1, 10), + (1.0000000000m, 10000000000, 10, 1, 0, 1, 11), + (0.1m, 1, 1, 1, -1, 1, 2), + (0.01m, 1, 2, 1, -2, 1, 3), + (0.001m, 1, 3, 1, -3, 1, 4), + (0.0001m, 1, 4, 1, -4, 1, 5), + (0.00001m, 1, 5, 1, -5, 1, 6), + (0.000001m, 1, 6, 1, -6, 1, 7), + (0.0000001m, 1, 7, 1, -7, 1, 8), + (0.00000001m, 1, 8, 1, -8, 1, 9), + (0.000000001m, 1, 9, 1, -9, 1, 10), + (0.0000000001m, 1, 10, 1, -10, 1, 11), + (12345678.9m, 123456789, 1, 123456789, -1, 1, 9), + (1234567.89m, 123456789, 2, 123456789, -2, 1, 9), + (123456.789m, 123456789, 3, 123456789, -3, 1, 9), + (12345.6789m, 123456789, 4, 123456789, -4, 1, 9), + (1234.56789m, 123456789, 5, 123456789, -5, 1, 9), + (123.456789m, 123456789, 6, 123456789, -6, 1, 9), + (12.3456789m, 123456789, 7, 123456789, -7, 1, 9), + (1.23456789m, 123456789, 8, 123456789, -8, 1, 9), + (0.123456789m, 123456789, 9, 123456789, -9, 1, 10), + (0.0123456789m, 123456789, 10, 123456789, -10, 1, 11), + (0.00123456789m, 123456789, 11, 123456789, -11, 1, 12), + (0.000123456789m, 123456789, 12, 123456789, -12, 1, 13), + (0.0000123456789m, 123456789, 13, 123456789, -13, 1, 14), + (0.00000123456789m, 123456789, 14, 123456789, -14, 1, 15), + (0.000000123456789m, 123456789, 15, 123456789, -15, 1, 16), + (0.0000000123456789m, 123456789, 16, 123456789, -16, 1, 17), + (0.00000000123456789m, 123456789, 17, 123456789, -17, 1, 18), + (0.000000000123456789m, 123456789, 18, 123456789, -18, 1, 19), + (123.456m, 123456, 3, 123456, -3, 1, 6), + (123.4560m, 1234560, 4, 123456, -3, 1, 7), + (123.45600m, 12345600, 5, 123456, -3, 1, 8), + (123.456000m, 123456000, 6, 123456, -3, 1, 9), + (123.4560000m, 1234560000, 7, 123456, -3, 1, 10), + (123.45600000m, 12345600000, 8, 123456, -3, 1, 11), + (123.456000000m, 123456000000, 9, 123456, -3, 1, 12), + (123.4560000000m, 1234560000000, 10, 123456, -3, 1, 13), + (123.45600000000m, 12345600000000, 11, 123456, -3, 1, 14), + (123.456000000000m, 123456000000000, 12, 123456, -3, 1, 15), + (123.4560000000000m, 1234560000000000, 13, 123456, -3, 1, 16), + (-1.0m, -10, 1, -1, 0, -1, 2), + (-1.00m, -100, 2, -1, 0, -1, 3), + (-1.000m, -1000, 3, -1, 0, -1, 4), + (-1.0000m, -10000, 4, -1, 0, -1, 5), + (-1.00000m, -100000, 5, -1, 0, -1, 6), + (-1.000000m, -1000000, 6, -1, 0, -1, 7), + (-1.0000000m, -10000000, 7, -1, 0, -1, 8), + (-1.00000000m, -100000000, 8, -1, 0, -1, 9), + (-1.000000000m, -1000000000, 9, -1, 0, -1, 10), + (-1.0000000000m, -10000000000, 10, -1, 0, -1, 11), + (-0.1m, -1, 1, -1, -1, -1, 2), + (-0.01m, -1, 2, -1, -2, -1, 3), + (-0.001m, -1, 3, -1, -3, -1, 4), + (-0.0001m, -1, 4, -1, -4, -1, 5), + (-0.00001m, -1, 5, -1, -5, -1, 6), + (-0.000001m, -1, 6, -1, -6, -1, 7), + (-0.0000001m, -1, 7, -1, -7, -1, 8), + (-0.00000001m, -1, 8, -1, -8, -1, 9), + (-0.000000001m, -1, 9, -1, -9, -1, 10), + (-0.0000000001m, -1, 10, -1, -10, -1, 11), + (-12345678.9m, -123456789, 1, -123456789, -1, -1, 9), + (-1234567.89m, -123456789, 2, -123456789, -2, -1, 9), + (-123456.789m, -123456789, 3, -123456789, -3, -1, 9), + (-12345.6789m, -123456789, 4, -123456789, -4, -1, 9), + (-1234.56789m, -123456789, 5, -123456789, -5, -1, 9), + (-123.456789m, -123456789, 6, -123456789, -6, -1, 9), + (-12.3456789m, -123456789, 7, -123456789, -7, -1, 9), + (-1.23456789m, -123456789, 8, -123456789, -8, -1, 9), + (-0.123456789m, -123456789, 9, -123456789, -9, -1, 10), + (-0.0123456789m, -123456789, 10, -123456789, -10, -1, 11), + (-0.00123456789m, -123456789, 11, -123456789, -11, -1, 12), + (-0.000123456789m, -123456789, 12, -123456789, -12, -1, 13), + (-0.0000123456789m, -123456789, 13, -123456789, -13, -1, 14), + (-0.00000123456789m, -123456789, 14, -123456789, -14, -1, 15), + (-0.000000123456789m, -123456789, 15, -123456789, -15, -1, 16), + (-0.0000000123456789m, -123456789, 16, -123456789, -16, -1, 17), + (-0.00000000123456789m, -123456789, 17, -123456789, -17, -1, 18), + (-0.000000000123456789m, -123456789, 18, -123456789, -18, -1, 19), + (-123.456m, -123456, 3, -123456, -3, -1, 6), + (-123.4560m, -1234560, 4, -123456, -3, -1, 7), + (-123.45600m, -12345600, 5, -123456, -3, -1, 8), + (-123.456000m, -123456000, 6, -123456, -3, -1, 9), + (-123.4560000m, -1234560000, 7, -123456, -3, -1, 10), + (-123.45600000m, -12345600000, 8, -123456, -3, -1, 11), + (-123.456000000m, -123456000000, 9, -123456, -3, -1, 12), + (-123.4560000000m, -1234560000000, 10, -123456, -3, -1, 13), + (-123.45600000000m, -12345600000000, 11, -123456, -3, -1, 14), + (-123.456000000000m, -123456000000000, 12, -123456, -3, -1, 15), + (-123.4560000000000m, -1234560000000000, 13, -123456, -3, -1, 16), + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach ((decimal value, BigInteger unscaledValue, int scale, BigInteger significand, int exponent, int sign, int precision) in Data) + yield return [value, unscaledValue, scale, significand, exponent, sign, precision]; + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoDoubleDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoDoubleDataAttribute.cs new file mode 100644 index 0000000..4790706 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoDoubleDataAttribute.cs @@ -0,0 +1,93 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class NumericsExtensionsToNumberInfoDoubleDataAttribute : DataAttribute +{ + private static readonly (double Value, BigInteger UnscaledValue, int Scale, BigInteger Significand, int Exponent, int Sign, int Precision)[] Data = + [ + (2.718281828459045, 2718281828459045L, 15, 2718281828459045L, -15, 1, 16), + (3.141592653589793, 3141592653589793, 15, 3141592653589793, -15, 1, 16), + (6.283185307179586, 6283185307179586, 15, 6283185307179586, -15, 1, 16), + (0.1, 1, 1, 1, -1, 1, 2), + (0.01, 1, 2, 1, -2, 1, 3), + (0.001, 1, 3, 1, -3, 1, 4), + (0.0001, 1, 4, 1, -4, 1, 5), + (1E-05, 1, 5, 1, -5, 1, 6), + (1E-06, 1, 6, 1, -6, 1, 7), + (1E-07, 1, 7, 1, -7, 1, 8), + (1E-08, 1, 8, 1, -8, 1, 9), + (1E-09, 1, 9, 1, -9, 1, 10), + (1E-10, 1, 10, 1, -10, 1, 11), + (12345678.9, 123456789, 1, 123456789, -1, 1, 9), + (1234567.89, 123456789, 2, 123456789, -2, 1, 9), + (123456.789, 123456789, 3, 123456789, -3, 1, 9), + (12345.6789, 123456789, 4, 123456789, -4, 1, 9), + (1234.56789, 123456789, 5, 123456789, -5, 1, 9), + (123.456789, 123456789, 6, 123456789, -6, 1, 9), + (12.3456789, 123456789, 7, 123456789, -7, 1, 9), + (1.23456789, 123456789, 8, 123456789, -8, 1, 9), + (0.123456789, 123456789, 9, 123456789, -9, 1, 10), + (0.0123456789, 123456789, 10, 123456789, -10, 1, 11), + (0.00123456789, 123456789, 11, 123456789, -11, 1, 12), + (0.000123456789, 123456789, 12, 123456789, -12, 1, 13), + (1.23456789E-05, 123456789, 13, 123456789, -13, 1, 14), + (1.23456789E-06, 123456789, 14, 123456789, -14, 1, 15), + (1.23456789E-07, 123456789, 15, 123456789, -15, 1, 16), + (1.23456789E-08, 123456789, 16, 123456789, -16, 1, 17), + (1.23456789E-09, 123456789, 17, 123456789, -17, 1, 18), + (1.23456789E-10, 123456789, 18, 123456789, -18, 1, 19), + (-0.1, -1, 1, -1, -1, -1, 2), + (-0.01, -1, 2, -1, -2, -1, 3), + (-0.001, -1, 3, -1, -3, -1, 4), + (-0.0001, -1, 4, -1, -4, -1, 5), + (-1E-05, -1, 5, -1, -5, -1, 6), + (-1E-06, -1, 6, -1, -6, -1, 7), + (-1E-07, -1, 7, -1, -7, -1, 8), + (-1E-08, -1, 8, -1, -8, -1, 9), + (-1E-09, -1, 9, -1, -9, -1, 10), + (-1E-10, -1, 10, -1, -10, -1, 11), + (-12345678.9, -123456789, 1, -123456789, -1, -1, 9), + (-1234567.89, -123456789, 2, -123456789, -2, -1, 9), + (-123456.789, -123456789, 3, -123456789, -3, -1, 9), + (-12345.6789, -123456789, 4, -123456789, -4, -1, 9), + (-1234.56789, -123456789, 5, -123456789, -5, -1, 9), + (-123.456789, -123456789, 6, -123456789, -6, -1, 9), + (-12.3456789, -123456789, 7, -123456789, -7, -1, 9), + (-1.23456789, -123456789, 8, -123456789, -8, -1, 9), + (-0.123456789, -123456789, 9, -123456789, -9, -1, 10), + (-0.0123456789, -123456789, 10, -123456789, -10, -1, 11), + (-0.00123456789, -123456789, 11, -123456789, -11, -1, 12), + (-0.000123456789, -123456789, 12, -123456789, -12, -1, 13), + (-1.23456789E-05, -123456789, 13, -123456789, -13, -1, 14), + (-1.23456789E-06, -123456789, 14, -123456789, -14, -1, 15), + (-1.23456789E-07, -123456789, 15, -123456789, -15, -1, 16), + (-1.23456789E-08, -123456789, 16, -123456789, -16, -1, 17), + (-1.23456789E-09, -123456789, 17, -123456789, -17, -1, 18), + (-1.23456789E-10, -123456789, 18, -123456789, -18, -1, 19) + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach ((double value, BigInteger unscaledValue, int scale, BigInteger significand, int exponent, int sign, int precision) in Data) + { + yield return [value, unscaledValue, scale, significand, exponent, sign, precision]; + } + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoFloatDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoFloatDataAttribute.cs new file mode 100644 index 0000000..e162940 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoFloatDataAttribute.cs @@ -0,0 +1,90 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class NumericsExtensionsToNumberInfoFloatDataAttribute : DataAttribute +{ + private static readonly (float Value, BigInteger UnscaledValue, int Scale, BigInteger Significand, int Exponent, int Sign, int Precision)[] Data = + [ + (0.1f, 1, 1, 1, -1, 1, 2), + (0.01f, 1, 2, 1, -2, 1, 3), + (0.001f, 1, 3, 1, -3, 1, 4), + (0.0001f, 1, 4, 1, -4, 1, 5), + (1E-05f, 1, 5, 1, -5, 1, 6), + (1E-06f, 1, 6, 1, -6, 1, 7), + (1E-07f, 1, 7, 1, -7, 1, 8), + (1E-08f, 1, 8, 1, -8, 1, 9), + (1E-09f, 1, 9, 1, -9, 1, 10), + (1E-10f, 1, 10, 1, -10, 1, 11), + (12345679f, 12345679, 0, 12345679, 0, 1, 8), + (1234567.9f, 12345679, 1, 12345679, -1, 1, 8), + (123456.79f, 12345679, 2, 12345679, -2, 1, 8), + (12345.679f, 12345679, 3, 12345679, -3, 1, 8), + (1234.5679f, 12345679, 4, 12345679, -4, 1, 8), + (123.45679f, 12345679, 5, 12345679, -5, 1, 8), + (12.345679f, 12345679, 6, 12345679, -6, 1, 8), + (1.2345679f, 12345679, 7, 12345679, -7, 1, 8), + (0.12345679f, 12345679, 8, 12345679, -8, 1, 9), + (0.012345679f, 12345679, 9, 12345679, -9, 1, 10), + (0.0012345678f, 12345678, 10, 12345678, -10, 1, 11), + (0.00012345679f, 12345679, 11, 12345679, -11, 1, 12), + (1.2345679E-05f, 12345679, 12, 12345679, -12, 1, 13), + (1.2345679E-06f, 12345679, 13, 12345679, -13, 1, 14), + (1.2345679E-07f, 12345679, 14, 12345679, -14, 1, 15), + (1.2345679E-08f, 12345679, 15, 12345679, -15, 1, 16), + (1.2345679E-09f, 12345679, 16, 12345679, -16, 1, 17), + (1.2345679E-10f, 12345679, 17, 12345679, -17, 1, 18), + (-0.1f, -1, 1, -1, -1, -1, 2), + (-0.01f, -1, 2, -1, -2, -1, 3), + (-0.001f, -1, 3, -1, -3, -1, 4), + (-0.0001f, -1, 4, -1, -4, -1, 5), + (-1E-05f, -1, 5, -1, -5, -1, 6), + (-1E-06f, -1, 6, -1, -6, -1, 7), + (-1E-07f, -1, 7, -1, -7, -1, 8), + (-1E-08f, -1, 8, -1, -8, -1, 9), + (-1E-09f, -1, 9, -1, -9, -1, 10), + (-1E-10f, -1, 10, -1, -10, -1, 11), + (-12345679f, -12345679, 0, -12345679, 0, -1, 8), + (-1234567.9f, -12345679, 1, -12345679, -1, -1, 8), + (-123456.79f, -12345679, 2, -12345679, -2, -1, 8), + (-12345.679f, -12345679, 3, -12345679, -3, -1, 8), + (-1234.5679f, -12345679, 4, -12345679, -4, -1, 8), + (-123.45679f, -12345679, 5, -12345679, -5, -1, 8), + (-12.345679f, -12345679, 6, -12345679, -6, -1, 8), + (-1.2345679f, -12345679, 7, -12345679, -7, -1, 8), + (-0.12345679f, -12345679, 8, -12345679, -8, -1, 9), + (-0.012345679f, -12345679, 9, -12345679, -9, -1, 10), + (-0.0012345678f, -12345678, 10, -12345678, -10, -1, 11), + (-0.00012345679f, -12345679, 11, -12345679, -11, -1, 12), + (-1.2345679E-05f, -12345679, 12, -12345679, -12, -1, 13), + (-1.2345679E-06f, -12345679, 13, -12345679, -13, -1, 14), + (-1.2345679E-07f, -12345679, 14, -12345679, -14, -1, 15), + (-1.2345679E-08f, -12345679, 15, -12345679, -15, -1, 16), + (-1.2345679E-09f, -12345679, 16, -12345679, -16, -1, 17), + (-1.2345679E-10f, -12345679, 17, -12345679, -17, -1, 18), + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach ((float value, BigInteger unscaledValue, int scale, BigInteger significand, int exponent, int sign, int precision) in Data) + { + yield return [value, unscaledValue, scale, significand, exponent, sign, precision]; + } + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoIntegerDataAttribute.cs b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoIntegerDataAttribute.cs new file mode 100644 index 0000000..c83d471 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/NumericsExtensionsToNumberInfoIntegerDataAttribute.cs @@ -0,0 +1,95 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using System.Reflection; +using Xunit.Sdk; + +namespace OnixLabs.Numerics.UnitTests.Data; + +public sealed class NumericsExtensionsToNumberInfoIntegerDataAttribute : DataAttribute +{ + private static readonly (Int128 Value, BigInteger UnscaledValue, int Scale, BigInteger Significand, int Exponent, int Sign, int Precision)[] Data = + [ + (0, 0, 0, 0, 0, 0, 1), + (1, 1, 0, 1, 0, 1, 1), + (2, 2, 0, 2, 0, 1, 1), + (3, 3, 0, 3, 0, 1, 1), + (4, 4, 0, 4, 0, 1, 1), + (5, 5, 0, 5, 0, 1, 1), + (6, 6, 0, 6, 0, 1, 1), + (7, 7, 0, 7, 0, 1, 1), + (8, 8, 0, 8, 0, 1, 1), + (9, 9, 0, 9, 0, 1, 1), + (10, 10, 0, 1, 1, 1, 2), + (100, 100, 0, 1, 2, 1, 3), + (1000, 1000, 0, 1, 3, 1, 4), + (10000, 10000, 0, 1, 4, 1, 5), + (100000, 100000, 0, 1, 5, 1, 6), + (1000000, 1000000, 0, 1, 6, 1, 7), + (10000000, 10000000, 0, 1, 7, 1, 8), + (100000000, 100000000, 0, 1, 8, 1, 9), + (1000000000, 1000000000, 0, 1, 9, 1, 10), + (10000000000, 10000000000, 0, 1, 10, 1, 11), + (-1, -1, 0, -1, 0, -1, 1), + (-2, -2, 0, -2, 0, -1, 1), + (-3, -3, 0, -3, 0, -1, 1), + (-4, -4, 0, -4, 0, -1, 1), + (-5, -5, 0, -5, 0, -1, 1), + (-6, -6, 0, -6, 0, -1, 1), + (-7, -7, 0, -7, 0, -1, 1), + (-8, -8, 0, -8, 0, -1, 1), + (-9, -9, 0, -9, 0, -1, 1), + (-10, -10, 0, -1, 1, -1, 2), + (-100, -100, 0, -1, 2, -1, 3), + (-1000, -1000, 0, -1, 3, -1, 4), + (-10000, -10000, 0, -1, 4, -1, 5), + (-100000, -100000, 0, -1, 5, -1, 6), + (-1000000, -1000000, 0, -1, 6, -1, 7), + (-10000000, -10000000, 0, -1, 7, -1, 8), + (-100000000, -100000000, 0, -1, 8, -1, 9), + (-1000000000, -1000000000, 0, -1, 9, -1, 10), + (-10000000000, -10000000000, 0, -1, 10, -1, 11), + (123456, 123456, 0, 123456, 0, 1, 6), + (123456000, 123456000, 0, 123456, 3, 1, 9), + (123456000000, 123456000000, 0, 123456, 6, 1, 12), + (-123456, -123456, 0, -123456, 0, -1, 6), + (-123456000, -123456000, 0, -123456, 3, -1, 9), + (-123456000000, -123456000000, 0, -123456, 6, -1, 12), + (sbyte.MaxValue, 127, 0, 127, 0, 1, 3), + (sbyte.MinValue, -128, 0, -128, 0, -1, 3), + (byte.MaxValue, 255, 0, 255, 0, 1, 3), + (byte.MinValue, 0, 0, 0, 0, 0, 1), + (short.MaxValue, 32767, 0, 32767, 0, 1, 5), + (short.MinValue, -32768, 0, -32768, 0, -1, 5), + (ushort.MaxValue, 65535, 0, 65535, 0, 1, 5), + (ushort.MinValue, 0, 0, 0, 0, 0, 1), + (int.MaxValue, 2147483647, 0, 2147483647, 0, 1, 10), + (int.MinValue, -2147483648, 0, -2147483648, 0, -1, 10), + (uint.MaxValue, 4294967295, 0, 4294967295, 0, 1, 10), + (uint.MinValue, 0, 0, 0, 0, 0, 1), + (long.MaxValue, 9223372036854775807, 0, 9223372036854775807, 0, 1, 19), + (long.MinValue, -9223372036854775808, 0, -9223372036854775808, 0, -1, 19), + (ulong.MaxValue, 18446744073709551615, 0, 18446744073709551615, 0, 1, 20), + (ulong.MinValue, 0, 0, 0, 0, 0, 1) + ]; + + public override IEnumerable GetData(MethodInfo testMethod) + { + foreach ((Int128 value, BigInteger unscaledValue, int scale, BigInteger significand, int exponent, int sign, int precision) in Data) + { + yield return [value, unscaledValue, scale, significand, exponent, sign, precision]; + } + } +} diff --git a/OnixLabs.Numerics.UnitTests.Data/OnixLabs.Numerics.UnitTests.Data.csproj b/OnixLabs.Numerics.UnitTests.Data/OnixLabs.Numerics.UnitTests.Data.csproj new file mode 100644 index 0000000..fd8fb90 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/OnixLabs.Numerics.UnitTests.Data.csproj @@ -0,0 +1,29 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/OnixLabs.Numerics.UnitTests.Data/TestDataGenerator.cs b/OnixLabs.Numerics.UnitTests.Data/TestDataGenerator.cs new file mode 100644 index 0000000..d15dcc2 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests.Data/TestDataGenerator.cs @@ -0,0 +1,952 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; + +namespace OnixLabs.Numerics.UnitTests.Data; + +internal static class TestDataGenerator +{ + private const int MinScale = 0; + private const int MaxScale = 28; + + private static readonly int[] DefaultValues = + [ + 0, + + +1, +2, +3, +4, +5, +6, +7, +8, +9, + +10, +100, +1_000, +10_000, +1_000_000_000, + +12, +123, +1_234, +12_345, +1_234_567_890, + + -1, -2, -3, -4, -5, -6, -7, -8, -9, + -10, -100, -1_000, -10_000, -1_000_000_000, + -12, -123, -1_234, -12_345, -1_234_567_890 + ]; + + private static readonly int[] DefaultScales = [0, 1, 2, 3, 4, 5, 10]; + + private static readonly ScaleMode[] DefaultModes = Enum.GetValues(); + + private static readonly decimal[] StaticValues = + [ + 0m, + 0.0m, + 0.00m, + 0.000m, + 0.0000m, + 0.00000m, + 0.000000m, + 0.0000000m, + 0.00000000m, + 0.000000000m, + 0.0000000000m, + 0.00000000000m, + 0.000000000000m, + 0.0000000000000m, + 0.00000000000000m, + 0.000000000000000m, + 0.0000000000000000m, + 0.00000000000000000m, + 0.000000000000000000m, + 0.0000000000000000000m, + 0.00000000000000000000m, + 0.000000000000000000000m, + 0.0000000000000000000000m, + 0.00000000000000000000000m, + 0.000000000000000000000000m, + 0.0000000000000000000000000m, + 0.00000000000000000000000000m, + 0.000000000000000000000000000m, + 1m, + 0.1m, + 0.01m, + 0.001m, + 0.0001m, + 0.00001m, + 0.000001m, + 0.0000001m, + 0.00000001m, + 0.000000001m, + 0.0000000001m, + 0.00000000001m, + 0.000000000001m, + 0.0000000000001m, + 0.00000000000001m, + 0.000000000000001m, + 0.0000000000000001m, + 0.00000000000000001m, + 0.000000000000000001m, + 0.0000000000000000001m, + 0.00000000000000000001m, + 0.000000000000000000001m, + 0.0000000000000000000001m, + 0.00000000000000000000001m, + 0.000000000000000000000001m, + 0.0000000000000000000000001m, + 0.00000000000000000000000001m, + 0.000000000000000000000000001m, + 1.0m, + 1.00m, + 1.000m, + 1.0000m, + 1.00000m, + 1.000000m, + 1.0000000m, + 1.00000000m, + 1.000000000m, + 1.0000000000m, + 1.00000000000m, + 1.000000000000m, + 1.0000000000000m, + 1.00000000000000m, + 1.000000000000000m, + 1.0000000000000000m, + 1.00000000000000000m, + 1.000000000000000000m, + 1.0000000000000000000m, + 1.00000000000000000000m, + 1.000000000000000000000m, + 1.0000000000000000000000m, + 1.00000000000000000000000m, + 1.000000000000000000000000m, + 1.0000000000000000000000000m, + 1.00000000000000000000000000m, + 1.000000000000000000000000000m, + 10m, + 0.10m, + 0.010m, + 0.0010m, + 0.00010m, + 0.000010m, + 0.0000010m, + 0.00000010m, + 0.000000010m, + 0.0000000010m, + 0.00000000010m, + 0.000000000010m, + 0.0000000000010m, + 0.00000000000010m, + 0.000000000000010m, + 0.0000000000000010m, + 0.00000000000000010m, + 0.000000000000000010m, + 0.0000000000000000010m, + 0.00000000000000000010m, + 0.000000000000000000010m, + 0.0000000000000000000010m, + 0.00000000000000000000010m, + 0.000000000000000000000010m, + 0.0000000000000000000000010m, + 0.00000000000000000000000010m, + 10.0m, + 10.00m, + 10.000m, + 10.0000m, + 10.00000m, + 10.000000m, + 10.0000000m, + 10.00000000m, + 10.000000000m, + 10.0000000000m, + 10.00000000000m, + 10.000000000000m, + 10.0000000000000m, + 10.00000000000000m, + 10.000000000000000m, + 10.0000000000000000m, + 10.00000000000000000m, + 10.000000000000000000m, + 10.0000000000000000000m, + 10.00000000000000000000m, + 10.000000000000000000000m, + 10.0000000000000000000000m, + 10.00000000000000000000000m, + 10.000000000000000000000000m, + 10.0000000000000000000000000m, + 10.00000000000000000000000000m, + 100m, + 0.100m, + 0.0100m, + 0.00100m, + 0.000100m, + 0.0000100m, + 0.00000100m, + 0.000000100m, + 0.0000000100m, + 0.00000000100m, + 0.000000000100m, + 0.0000000000100m, + 0.00000000000100m, + 0.000000000000100m, + 0.0000000000000100m, + 0.00000000000000100m, + 0.000000000000000100m, + 0.0000000000000000100m, + 0.00000000000000000100m, + 0.000000000000000000100m, + 0.0000000000000000000100m, + 0.00000000000000000000100m, + 0.000000000000000000000100m, + 0.0000000000000000000000100m, + 100.0m, + 100.00m, + 100.000m, + 100.0000m, + 100.00000m, + 100.000000m, + 100.0000000m, + 100.00000000m, + 100.000000000m, + 100.0000000000m, + 100.00000000000m, + 100.000000000000m, + 100.0000000000000m, + 100.00000000000000m, + 100.000000000000000m, + 100.0000000000000000m, + 100.00000000000000000m, + 100.000000000000000000m, + 100.0000000000000000000m, + 100.00000000000000000000m, + 100.000000000000000000000m, + 100.0000000000000000000000m, + 100.00000000000000000000000m, + 100.000000000000000000000000m, + 100.0000000000000000000000000m, + 127m, + 12.7m, + 1.27m, + 0.127m, + 0.0127m, + 0.00127m, + 0.000127m, + 0.0000127m, + 0.00000127m, + 0.000000127m, + 0.0000000127m, + 0.00000000127m, + 0.000000000127m, + 0.0000000000127m, + 0.00000000000127m, + 0.000000000000127m, + 0.0000000000000127m, + 0.00000000000000127m, + 0.000000000000000127m, + 0.0000000000000000127m, + 0.00000000000000000127m, + 0.000000000000000000127m, + 0.0000000000000000000127m, + 0.00000000000000000000127m, + 0.000000000000000000000127m, + 0.0000000000000000000000127m, + 127.0m, + 127.00m, + 127.000m, + 127.0000m, + 127.00000m, + 127.000000m, + 127.0000000m, + 127.00000000m, + 127.000000000m, + 127.0000000000m, + 127.00000000000m, + 127.000000000000m, + 127.0000000000000m, + 127.00000000000000m, + 127.000000000000000m, + 127.0000000000000000m, + 127.00000000000000000m, + 127.000000000000000000m, + 127.0000000000000000000m, + 127.00000000000000000000m, + 127.000000000000000000000m, + 127.0000000000000000000000m, + 127.00000000000000000000000m, + 127.000000000000000000000000m, + 127.0000000000000000000000000m, + 255m, + 25.5m, + 2.55m, + 0.255m, + 0.0255m, + 0.00255m, + 0.000255m, + 0.0000255m, + 0.00000255m, + 0.000000255m, + 0.0000000255m, + 0.00000000255m, + 0.000000000255m, + 0.0000000000255m, + 0.00000000000255m, + 0.000000000000255m, + 0.0000000000000255m, + 0.00000000000000255m, + 0.000000000000000255m, + 0.0000000000000000255m, + 0.00000000000000000255m, + 0.000000000000000000255m, + 0.0000000000000000000255m, + 0.00000000000000000000255m, + 0.000000000000000000000255m, + 0.0000000000000000000000255m, + 255.0m, + 255.00m, + 255.000m, + 255.0000m, + 255.00000m, + 255.000000m, + 255.0000000m, + 255.00000000m, + 255.000000000m, + 255.0000000000m, + 255.00000000000m, + 255.000000000000m, + 255.0000000000000m, + 255.00000000000000m, + 255.000000000000000m, + 255.0000000000000000m, + 255.00000000000000000m, + 255.000000000000000000m, + 255.0000000000000000000m, + 255.00000000000000000000m, + 255.000000000000000000000m, + 255.0000000000000000000000m, + 255.00000000000000000000000m, + 255.000000000000000000000000m, + 255.0000000000000000000000000m, + 32767m, + 3276.7m, + 327.67m, + 32.767m, + 3.2767m, + 0.32767m, + 0.032767m, + 0.0032767m, + 0.00032767m, + 0.000032767m, + 0.0000032767m, + 0.00000032767m, + 0.000000032767m, + 0.0000000032767m, + 0.00000000032767m, + 0.000000000032767m, + 0.0000000000032767m, + 0.00000000000032767m, + 0.000000000000032767m, + 0.0000000000000032767m, + 0.00000000000000032767m, + 0.000000000000000032767m, + 0.0000000000000000032767m, + 0.00000000000000000032767m, + 32767.0m, + 32767.00m, + 32767.000m, + 32767.0000m, + 32767.00000m, + 32767.000000m, + 32767.0000000m, + 32767.00000000m, + 32767.000000000m, + 32767.0000000000m, + 32767.00000000000m, + 32767.000000000000m, + 32767.0000000000000m, + 32767.00000000000000m, + 32767.000000000000000m, + 32767.0000000000000000m, + 32767.00000000000000000m, + 32767.000000000000000000m, + 32767.0000000000000000000m, + 32767.00000000000000000000m, + 32767.000000000000000000000m, + 32767.0000000000000000000000m, + 32767.00000000000000000000000m, + 65535m, + 6553.5m, + 655.35m, + 65.535m, + 6.5535m, + 0.65535m, + 0.065535m, + 0.0065535m, + 0.00065535m, + 0.000065535m, + 0.0000065535m, + 0.00000065535m, + 0.000000065535m, + 0.0000000065535m, + 0.00000000065535m, + 0.000000000065535m, + 0.0000000000065535m, + 0.00000000000065535m, + 0.000000000000065535m, + 0.0000000000000065535m, + 0.00000000000000065535m, + 0.000000000000000065535m, + 0.0000000000000000065535m, + 0.00000000000000000065535m, + 65535.0m, + 65535.00m, + 65535.000m, + 65535.0000m, + 65535.00000m, + 65535.000000m, + 65535.0000000m, + 65535.00000000m, + 65535.000000000m, + 65535.0000000000m, + 65535.00000000000m, + 65535.000000000000m, + 65535.0000000000000m, + 65535.00000000000000m, + 65535.000000000000000m, + 65535.0000000000000000m, + 65535.00000000000000000m, + 65535.000000000000000000m, + 65535.0000000000000000000m, + 65535.00000000000000000000m, + 65535.000000000000000000000m, + 65535.0000000000000000000000m, + 65535.00000000000000000000000m, + 2147483647m, + 214748364.7m, + 21474836.47m, + 2147483.647m, + 214748.3647m, + 21474.83647m, + 2147.483647m, + 214.7483647m, + 21.47483647m, + 2.147483647m, + 0.2147483647m, + 0.02147483647m, + 0.002147483647m, + 0.0002147483647m, + 0.00002147483647m, + 0.000002147483647m, + 0.0000002147483647m, + 0.00000002147483647m, + 0.000000002147483647m, + 2147483647.0m, + 2147483647.00m, + 2147483647.000m, + 2147483647.0000m, + 2147483647.00000m, + 2147483647.000000m, + 2147483647.0000000m, + 2147483647.00000000m, + 2147483647.000000000m, + 2147483647.0000000000m, + 2147483647.00000000000m, + 2147483647.000000000000m, + 2147483647.0000000000000m, + 2147483647.00000000000000m, + 2147483647.000000000000000m, + 2147483647.0000000000000000m, + 2147483647.00000000000000000m, + 2147483647.000000000000000000m, + 4294967295m, + 429496729.5m, + 42949672.95m, + 4294967.295m, + 429496.7295m, + 42949.67295m, + 4294.967295m, + 429.4967295m, + 42.94967295m, + 4.294967295m, + 0.4294967295m, + 0.04294967295m, + 0.004294967295m, + 0.0004294967295m, + 0.00004294967295m, + 0.000004294967295m, + 0.0000004294967295m, + 0.00000004294967295m, + 0.000000004294967295m, + 4294967295.0m, + 4294967295.00m, + 4294967295.000m, + 4294967295.0000m, + 4294967295.00000m, + 4294967295.000000m, + 4294967295.0000000m, + 4294967295.00000000m, + 4294967295.000000000m, + 4294967295.0000000000m, + 4294967295.00000000000m, + 4294967295.000000000000m, + 4294967295.0000000000000m, + 4294967295.00000000000000m, + 4294967295.000000000000000m, + 4294967295.0000000000000000m, + 4294967295.00000000000000000m, + 4294967295.000000000000000000m, + 9223372036854775807m, + 922337203685477580.7m, + 92233720368547758.07m, + 9223372036854775.807m, + 922337203685477.5807m, + 92233720368547.75807m, + 9223372036854.775807m, + 922337203685.4775807m, + 92233720368.54775807m, + 9223372036.854775807m, + 9223372036854775807.0m, + 9223372036854775807.00m, + 9223372036854775807.000m, + 9223372036854775807.0000m, + 9223372036854775807.00000m, + 9223372036854775807.000000m, + 9223372036854775807.0000000m, + 9223372036854775807.00000000m, + 9223372036854775807.000000000m, + 18446744073709551615m, + 1844674407370955161.5m, + 184467440737095516.15m, + 18446744073709551.615m, + 1844674407370955.1615m, + 184467440737095.51615m, + 18446744073709.551615m, + 1844674407370.9551615m, + 184467440737.09551615m, + 18446744073709551615.0m, + 18446744073709551615.00m, + 18446744073709551615.000m, + 18446744073709551615.0000m, + 18446744073709551615.00000m, + 18446744073709551615.000000m, + 18446744073709551615.0000000m, + 18446744073709551615.00000000m, + -1m, + -0.1m, + -0.01m, + -0.001m, + -0.0001m, + -0.00001m, + -0.000001m, + -0.0000001m, + -0.00000001m, + -0.000000001m, + -0.0000000001m, + -0.00000000001m, + -0.000000000001m, + -0.0000000000001m, + -0.00000000000001m, + -0.000000000000001m, + -0.0000000000000001m, + -0.00000000000000001m, + -0.000000000000000001m, + -0.0000000000000000001m, + -0.00000000000000000001m, + -0.000000000000000000001m, + -0.0000000000000000000001m, + -0.00000000000000000000001m, + -0.000000000000000000000001m, + -0.0000000000000000000000001m, + -0.00000000000000000000000001m, + -0.000000000000000000000000001m, + -1.0m, + -1.00m, + -1.000m, + -1.0000m, + -1.00000m, + -1.000000m, + -1.0000000m, + -1.00000000m, + -1.000000000m, + -1.0000000000m, + -1.00000000000m, + -1.000000000000m, + -1.0000000000000m, + -1.00000000000000m, + -1.000000000000000m, + -1.0000000000000000m, + -1.00000000000000000m, + -1.000000000000000000m, + -1.0000000000000000000m, + -1.00000000000000000000m, + -1.000000000000000000000m, + -1.0000000000000000000000m, + -1.00000000000000000000000m, + -1.000000000000000000000000m, + -1.0000000000000000000000000m, + -1.00000000000000000000000000m, + -1.000000000000000000000000000m, + -10m, + -0.10m, + -0.010m, + -0.0010m, + -0.00010m, + -0.000010m, + -0.0000010m, + -0.00000010m, + -0.000000010m, + -0.0000000010m, + -0.00000000010m, + -0.000000000010m, + -0.0000000000010m, + -0.00000000000010m, + -0.000000000000010m, + -0.0000000000000010m, + -0.00000000000000010m, + -0.000000000000000010m, + -0.0000000000000000010m, + -0.00000000000000000010m, + -0.000000000000000000010m, + -0.0000000000000000000010m, + -0.00000000000000000000010m, + -0.000000000000000000000010m, + -0.0000000000000000000000010m, + -0.00000000000000000000000010m, + -10.0m, + -10.00m, + -10.000m, + -10.0000m, + -10.00000m, + -10.000000m, + -10.0000000m, + -10.00000000m, + -10.000000000m, + -10.0000000000m, + -10.00000000000m, + -10.000000000000m, + -10.0000000000000m, + -10.00000000000000m, + -10.000000000000000m, + -10.0000000000000000m, + -10.00000000000000000m, + -10.000000000000000000m, + -10.0000000000000000000m, + -10.00000000000000000000m, + -10.000000000000000000000m, + -10.0000000000000000000000m, + -10.00000000000000000000000m, + -10.000000000000000000000000m, + -10.0000000000000000000000000m, + -10.00000000000000000000000000m, + -100m, + -0.100m, + -0.0100m, + -0.00100m, + -0.000100m, + -0.0000100m, + -0.00000100m, + -0.000000100m, + -0.0000000100m, + -0.00000000100m, + -0.000000000100m, + -0.0000000000100m, + -0.00000000000100m, + -0.000000000000100m, + -0.0000000000000100m, + -0.00000000000000100m, + -0.000000000000000100m, + -0.0000000000000000100m, + -0.00000000000000000100m, + -0.000000000000000000100m, + -0.0000000000000000000100m, + -0.00000000000000000000100m, + -0.000000000000000000000100m, + -0.0000000000000000000000100m, + -100.0m, + -100.00m, + -100.000m, + -100.0000m, + -100.00000m, + -100.000000m, + -100.0000000m, + -100.00000000m, + -100.000000000m, + -100.0000000000m, + -100.00000000000m, + -100.000000000000m, + -100.0000000000000m, + -100.00000000000000m, + -100.000000000000000m, + -100.0000000000000000m, + -100.00000000000000000m, + -100.000000000000000000m, + -100.0000000000000000000m, + -100.00000000000000000000m, + -100.000000000000000000000m, + -100.0000000000000000000000m, + -100.00000000000000000000000m, + -100.000000000000000000000000m, + -100.0000000000000000000000000m, + -128m, + -12.8m, + -1.28m, + -0.128m, + -0.0128m, + -0.00128m, + -0.000128m, + -0.0000128m, + -0.00000128m, + -0.000000128m, + -0.0000000128m, + -0.00000000128m, + -0.000000000128m, + -0.0000000000128m, + -0.00000000000128m, + -0.000000000000128m, + -0.0000000000000128m, + -0.00000000000000128m, + -0.000000000000000128m, + -0.0000000000000000128m, + -0.00000000000000000128m, + -0.000000000000000000128m, + -0.0000000000000000000128m, + -0.00000000000000000000128m, + -0.000000000000000000000128m, + -0.0000000000000000000000128m, + -128.0m, + -128.00m, + -128.000m, + -128.0000m, + -128.00000m, + -128.000000m, + -128.0000000m, + -128.00000000m, + -128.000000000m, + -128.0000000000m, + -128.00000000000m, + -128.000000000000m, + -128.0000000000000m, + -128.00000000000000m, + -128.000000000000000m, + -128.0000000000000000m, + -128.00000000000000000m, + -128.000000000000000000m, + -128.0000000000000000000m, + -128.00000000000000000000m, + -128.000000000000000000000m, + -128.0000000000000000000000m, + -128.00000000000000000000000m, + -128.000000000000000000000000m, + -128.0000000000000000000000000m, + -32768m, + -3276.8m, + -327.68m, + -32.768m, + -3.2768m, + -0.32768m, + -0.032768m, + -0.0032768m, + -0.00032768m, + -0.000032768m, + -0.0000032768m, + -0.00000032768m, + -0.000000032768m, + -0.0000000032768m, + -0.00000000032768m, + -0.000000000032768m, + -0.0000000000032768m, + -0.00000000000032768m, + -0.000000000000032768m, + -0.0000000000000032768m, + -0.00000000000000032768m, + -0.000000000000000032768m, + -0.0000000000000000032768m, + -0.00000000000000000032768m, + -32768.0m, + -32768.00m, + -32768.000m, + -32768.0000m, + -32768.00000m, + -32768.000000m, + -32768.0000000m, + -32768.00000000m, + -32768.000000000m, + -32768.0000000000m, + -32768.00000000000m, + -32768.000000000000m, + -32768.0000000000000m, + -32768.00000000000000m, + -32768.000000000000000m, + -32768.0000000000000000m, + -32768.00000000000000000m, + -32768.000000000000000000m, + -32768.0000000000000000000m, + -32768.00000000000000000000m, + -32768.000000000000000000000m, + -32768.0000000000000000000000m, + -32768.00000000000000000000000m, + -2147483648m, + -214748364.8m, + -21474836.48m, + -2147483.648m, + -214748.3648m, + -21474.83648m, + -2147.483648m, + -214.7483648m, + -21.47483648m, + -2.147483648m, + -0.2147483648m, + -0.02147483648m, + -0.002147483648m, + -0.0002147483648m, + -0.00002147483648m, + -0.000002147483648m, + -0.0000002147483648m, + -0.00000002147483648m, + -0.000000002147483648m, + -2147483648.0m, + -2147483648.00m, + -2147483648.000m, + -2147483648.0000m, + -2147483648.00000m, + -2147483648.000000m, + -2147483648.0000000m, + -2147483648.00000000m, + -2147483648.000000000m, + -2147483648.0000000000m, + -2147483648.00000000000m, + -2147483648.000000000000m, + -2147483648.0000000000000m, + -2147483648.00000000000000m, + -2147483648.000000000000000m, + -2147483648.0000000000000000m, + -2147483648.00000000000000000m, + -2147483648.000000000000000000m, + -9223372036854775808m, + -922337203685477580.8m, + -92233720368547758.08m, + -9223372036854775.808m, + -922337203685477.5808m, + -92233720368547.75808m, + -9223372036854.775808m, + -922337203685.4775808m, + -92233720368.54775808m, + -9223372036.854775808m, + -9223372036854775808.0m, + -9223372036854775808.00m, + -9223372036854775808.000m, + -9223372036854775808.0000m, + -9223372036854775808.00000m, + -9223372036854775808.000000m, + -9223372036854775808.0000000m, + -9223372036854775808.00000000m, + -9223372036854775808.000000000m, + ]; + + private static readonly CultureInfo[] Cultures = + [ + CultureInfo.InvariantCulture, + CultureInfo.GetCultureInfo("ar-001"), // Arabic (world) + CultureInfo.GetCultureInfo("ar-AE"), // Arabic (United Arab Emirates) + CultureInfo.GetCultureInfo("en-001"), // English (world) + CultureInfo.GetCultureInfo("en-150"), // English (Europe) + CultureInfo.GetCultureInfo("en-GB"), // English (United Kingdom) + CultureInfo.GetCultureInfo("en-US"), // English (United States) + CultureInfo.GetCultureInfo("en-US-POSIX"), // English (United States, Computer) + CultureInfo.GetCultureInfo("en-CV"), // English (Cape Verde) + CultureInfo.GetCultureInfo("kea-CV"), // Kabuverdianu (Cape Verde) + CultureInfo.GetCultureInfo("pt-CV"), // Portuguese (Cape Verde) + CultureInfo.GetCultureInfo("eu"), // Basque + CultureInfo.GetCultureInfo("eu-ES"), // Basque (Spain) + CultureInfo.GetCultureInfo("bg-BG"), // Bulgarian (Bulgaria) + CultureInfo.GetCultureInfo("de-DE"), // German (Germany) + CultureInfo.GetCultureInfo("es-ES"), // Spanish (Spain) + CultureInfo.GetCultureInfo("fi-FI"), // Finnish (Finland) + CultureInfo.GetCultureInfo("fo-FO"), // Faroese (Faroe Islands) + CultureInfo.GetCultureInfo("fr-FR"), // French (France) + CultureInfo.GetCultureInfo("hr-HR"), // Croatian (Croatia) + CultureInfo.GetCultureInfo("hu-HU"), // Hungarian (Hungary) + CultureInfo.GetCultureInfo("id-ID"), // Indonesian (Indonesia) + CultureInfo.GetCultureInfo("is-IS"), // Icelandic (Iceland) + CultureInfo.GetCultureInfo("it-IT"), // Italian (Italy) + CultureInfo.GetCultureInfo("lt-LT"), // Lithuanian (Lithuania) + CultureInfo.GetCultureInfo("lv-LV"), // Latvian (Latvia) + CultureInfo.GetCultureInfo("mg-MG"), // Malagasy (Madagascar) + CultureInfo.GetCultureInfo("mk-MK"), // Macedonian (North Macedonia) + CultureInfo.GetCultureInfo("mn-MN"), // Mongolian (Mongolia) + CultureInfo.GetCultureInfo("mt-MT"), // Maltese (Malta) + CultureInfo.GetCultureInfo("nl-NL"), // Dutch (Netherlands) + CultureInfo.GetCultureInfo("pl-PL"), // Polish (Poland) + CultureInfo.GetCultureInfo("pt-PT"), // Portuguese (Portugal) + CultureInfo.GetCultureInfo("ro-RO"), // Romanian (Romania) + CultureInfo.GetCultureInfo("ru-RU"), // Russian (Russia) + CultureInfo.GetCultureInfo("rw-RW"), // Kinyarwanda (Rwanda) + CultureInfo.GetCultureInfo("se-SE"), // Northern Sami (Sweden) + CultureInfo.GetCultureInfo("sk-SK"), // Slovak (Slovakia) + CultureInfo.GetCultureInfo("so-SO"), // Somali (Somalia) + CultureInfo.GetCultureInfo("th-TH"), // Thai (Thailand) + CultureInfo.GetCultureInfo("to-TO"), // Tongan (Tonga) + CultureInfo.GetCultureInfo("tr-TR"), // Turkish (Türkiye) + CultureInfo.GetCultureInfo("zh-Hans-CN"), // Chinese, Simplified (China mainland) + CultureInfo.GetCultureInfo("zh-Hant-CN"), // Chinese, Traditional (China mainland) + ]; + + public static IEnumerable GenerateScaledValues( + IEnumerable? values = null, + IEnumerable? scales = null, + IEnumerable? modes = null) + { + foreach (ScaleMode mode in modes ?? DefaultModes) + foreach (int value in values ?? DefaultValues) + foreach (int scale in scales ?? DefaultScales) + yield return value.ToDecimal(scale, mode); + } + + public static IEnumerable GenerateRandomValues(int count = 100, int seed = default) + { + Random random = new(seed); + + for (int index = 0; index < count; index++) + yield return random.Next(int.MinValue, int.MaxValue).ToDecimal(random.Next(0, 10)); + } + + public static IEnumerable GenerateScaledMaxValues() + { + foreach (int scale in GenerateScaleValues()) + yield return ((Int128)decimal.MaxValue).ToDecimal(scale); + } + + public static IEnumerable GenerateScaledMinValues() + { + foreach (int scale in GenerateScaleValues()) + yield return ((Int128)decimal.MinValue).ToDecimal(scale); + } + + public static IEnumerable GenerateConstantValues() + { + yield return decimal.Zero; + yield return decimal.One; + yield return decimal.MinusOne; + yield return decimal.MaxValue; + yield return decimal.MinValue; + } + + public static IEnumerable GenerateStaticValues() + { + return StaticValues; + } + + public static IEnumerable GenerateCultures() + { + return Cultures; + } + + public static IEnumerable GetMidpointRoundingModes() + { + return Enum.GetValues(); + } + + public static IEnumerable GenerateScaleValues(int min = MinScale, int max = MaxScale) + { + for (int scale = min; scale <= max; scale++) yield return scale; + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticAbsTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticAbsTests.cs new file mode 100644 index 0000000..dabd13e --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticAbsTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticAbsTests +{ + [BigDecimalArithmeticAbsData] + [Theory(DisplayName = "BigDecimal.Abs should produce the expected result.")] + public void BigDecimalAbsShouldProduceExpectedResult(decimal value) + { + // Given + decimal expected = decimal.Abs(value); + + // When + BigDecimal actual = BigDecimal.Abs(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticAdditionTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticAdditionTests.cs new file mode 100644 index 0000000..80fd93e --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticAdditionTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticAdditionTests +{ + [BigDecimalArithmeticAdditionData] + [Theory(DisplayName = "BigDecimal.Add should produce the expected result.")] + public void BigDecimalAddShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + decimal expected = left + right; + + // When + BigDecimal actual = BigDecimal.Add(left, right).Round(expected.Scale); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticDecrementTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticDecrementTests.cs new file mode 100644 index 0000000..139206e --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticDecrementTests.cs @@ -0,0 +1,52 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticDecrementTests +{ + [Theory(DisplayName = "BigDecimal.Decrement should produce the expected result.")] + [InlineData(-1, -2)] + [InlineData(0, -1)] + [InlineData(1, 0)] + [InlineData(10, 9)] + [InlineData(1000, 999)] + [InlineData(-1000, -1001)] + public void BigDecimalDecrementShouldProduceExpectedResult(double value, double expected) + { + // When + BigDecimal actual = BigDecimal.Decrement(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BigDecimal.DecrementFraction should produce the expected result.")] + [InlineData(-1.2, -1.3)] + [InlineData(0.2, 0.1)] + [InlineData(1.02, 1.01)] + [InlineData(10.999, 10.998)] + [InlineData(1000.02, 1000.01)] + [InlineData(-1000.01, -1000.02)] + public void BigDecimalDecrementFractionShouldProduceExpectedResult(double value, double expected) + { + // When + BigDecimal actual = BigDecimal.DecrementFraction(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticDivisionTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticDivisionTests.cs new file mode 100644 index 0000000..e08a57b --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticDivisionTests.cs @@ -0,0 +1,60 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticDivisionTests +{ + private static readonly BigDecimalDivisionEqualityComparer Comparer = new(); + + [BigDecimalArithmeticDivisionData] + [Theory(DisplayName = "BigDecimal.Divide should produce the expected result")] + public void BigDecimalDivideShouldProduceExpectedResult(decimal left, decimal right, MidpointRounding mode, Guid _) + { + // Given + decimal expected = decimal.Round(left / right, left.Scale, mode); + + // When + BigDecimal actual = BigDecimal.Divide(left, right, mode); + + // Then + Assert.Equal(expected, actual, Comparer); + } + + /// + /// Represents an equality comparer that is used specifically for tests. Notably, this comparer allows + /// for deltas of zero, or one for cases where provides greater rounding accuracy than . + /// + private sealed class BigDecimalDivisionEqualityComparer : IEqualityComparer + { + public bool Equals(BigDecimal x, BigDecimal y) + { + int scale = BigDecimal.MaxScale(x, y); + (BigInteger left, BigInteger right) = BigDecimal.NormalizeUnscaledValues(x, y); + BigDecimal leftNormalized = new(left, scale); + BigDecimal rightNormalized = new(right, scale); + + return (int)GenericMath.Delta(leftNormalized.UnscaledValue, rightNormalized.UnscaledValue) is 1 or 0; + } + + public int GetHashCode(BigDecimal obj) + { + return HashCode.Combine(obj.ToNumberInfo()); + } + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticIncrementTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticIncrementTests.cs new file mode 100644 index 0000000..912ce6c --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticIncrementTests.cs @@ -0,0 +1,52 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticIncrementTests +{ + [Theory(DisplayName = "BigDecimal.Increment should produce the expected result.")] + [InlineData(-1, 0)] + [InlineData(0, 1)] + [InlineData(1, 2)] + [InlineData(10, 11)] + [InlineData(1000, 1001)] + [InlineData(-1000, -999)] + public void BigDecimalIncrementShouldProduceExpectedResult(double value, double expected) + { + // When + BigDecimal actual = BigDecimal.Increment(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BigDecimal.IncrementFraction should produce the expected result.")] + [InlineData(-1.2, -1.1)] + [InlineData(0.2, 0.3)] + [InlineData(1.02, 1.03)] + [InlineData(10.998, 10.999)] + [InlineData(1000.02, 1000.03)] + [InlineData(-1000.02, -1000.01)] + public void BigDecimalIncrementFractionShouldProduceExpectedResult(double value, double expected) + { + // When + BigDecimal actual = BigDecimal.IncrementFraction(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticModulusTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticModulusTests.cs new file mode 100644 index 0000000..b31f53d --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticModulusTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticModulusTests +{ + [BigDecimalArithmeticModulusData] + [Theory(DisplayName = "BigDecimal.Mod should produce the expected result")] + public void BigDecimalModShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + decimal expected = left % right; + + // When + BigDecimal actual = BigDecimal.Mod(left, right).Round(expected.Scale); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticMultiplicationTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticMultiplicationTests.cs new file mode 100644 index 0000000..fc3f252 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticMultiplicationTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticMultiplicationTests +{ + [BigDecimalArithmeticMultiplicationData] + [Theory(DisplayName = "BigDecimal.Multiply should produce the expected result")] + public void BigDecimalMultiplyShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + decimal expected = left * right; + + // When + BigDecimal actual = BigDecimal.Multiply(left, right).Round(expected.Scale); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticPowTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticPowTests.cs new file mode 100644 index 0000000..724b1e2 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticPowTests.cs @@ -0,0 +1,32 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticPowTests +{ + [BigDecimalArithmeticPowData] + [Theory(DisplayName = "BigDecimal.Pow should produce the expected result")] + public void BigDecimalPowShouldProduceExpectedResult(decimal value, int exponent, decimal expected) + { + // When + BigDecimal actual = BigDecimal.Pow(value, exponent); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticRoundTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticRoundTests.cs new file mode 100644 index 0000000..27bf4d1 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticRoundTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticRoundTests +{ + [BigDecimalArithmeticRoundData] + [Theory(DisplayName = "BigDecimal.Round should produce the correct result")] + public void BigDecimalRoundShouldProduceExpectedResult(decimal value, byte scale, MidpointRounding mode, Guid _) + { + // Given + decimal expected = decimal.Round(value, scale, mode); + + // When + BigDecimal actual = BigDecimal.Round(value, scale, mode); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticScaleTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticScaleTests.cs new file mode 100644 index 0000000..aebc0f6 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticScaleTests.cs @@ -0,0 +1,32 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticScaleTests +{ + [BigDecimalArithmeticScaleData] + [Theory(DisplayName = "BigDecimal.SetScale should produce the expected result")] + public void BigDecimalSetScaleShouldProduceExpectedResult(decimal value, int scale, MidpointRounding mode, decimal expected) + { + // When + BigDecimal actual = value.ToBigDecimal().SetScale(scale, mode); + + // then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticSubtractionTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticSubtractionTests.cs new file mode 100644 index 0000000..8d11e93 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticSubtractionTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticSubtractionTests +{ + [BigDecimalArithmeticSubtractionData] + [Theory(DisplayName = "BigDecimal.Subtract should produce the expected result.")] + public void BigDecimalSubtractShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + decimal expected = left - right; + + // When + BigDecimal actual = BigDecimal.Subtract(left, right).Round(expected.Scale); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticTrimTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticTrimTests.cs new file mode 100644 index 0000000..30007ca --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticTrimTests.cs @@ -0,0 +1,32 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticTrimTests +{ + [BigDecimalArithmeticTrimData] + [Theory(DisplayName = "BigDecimal.TrimTrailingZeros should produce the expected result")] + public void BigDecimalTrimTrailingZerosShouldProduceExpectedResult(decimal value, decimal expected) + { + // When + BigDecimal actual = BigDecimal.TrimTrailingZeros(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticTruncateTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticTruncateTests.cs new file mode 100644 index 0000000..1caffc6 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticTruncateTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticTruncateTests +{ + [BigDecimalArithmeticTruncateData] + [Theory(DisplayName = "BigDecimal.Truncate should produce the expected result")] + public void BigDecimalTruncateShouldProduceExpectedResult(decimal value, Guid _) + { + // Given + decimal expected = decimal.Truncate(value); + + // When + BigDecimal actual = BigDecimal.Truncate(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticUnaryAdditionTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticUnaryAdditionTests.cs new file mode 100644 index 0000000..df48ba0 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticUnaryAdditionTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticUnaryAdditionTests +{ + [BigDecimalArithmeticUnaryAdditionData] + [Theory(DisplayName = "BigDecimal.UnaryAdd should produce the expected result")] + public void BigDecimalUnaryAddShouldProduceExpectedResult(decimal value) + { + // Given + decimal expected = +value; + + // When + BigDecimal actual = BigDecimal.UnaryAdd(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticUnarySubtractionTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticUnarySubtractionTests.cs new file mode 100644 index 0000000..a2e81bf --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalArithmeticUnarySubtractionTests.cs @@ -0,0 +1,35 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalArithmeticUnarySubtractionTests +{ + [BigDecimalArithmeticUnarySubtractionData] + [Theory(DisplayName = "BigDecimal.UnarySubtract should produce the expected result")] + public void BigDecimalUnarySubtractShouldProduceExpectedResult(decimal value) + { + // Given + decimal expected = -value; + + // When + BigDecimal actual = BigDecimal.UnarySubtract(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalComparableMinMaxTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalComparableMinMaxTests.cs new file mode 100644 index 0000000..fa81607 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalComparableMinMaxTests.cs @@ -0,0 +1,167 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalComparableMinMaxTests +{ + [Theory(DisplayName = "BigDecimal.Min should produce the expected result")] + [InlineData(0, 0, 0)] + [InlineData(1, 0, 0)] + [InlineData(1, 1, 1)] + [InlineData(1.1, 0.1, 0.1)] + [InlineData(1.1, 1.2, 1.1)] + [InlineData(0.01, 0.02, 0.01)] + [InlineData(-0.01, -0.02, -0.02)] + public void BigDecimalMinShouldProduceExpectedResult(double left, double right, double expected) + { + // When + BigDecimal actual = BigDecimal.Min(left, right); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BigDecimal.Max should produce the expected result")] + [InlineData(0, 0, 0)] + [InlineData(1, 0, 1)] + [InlineData(1, 1, 1)] + [InlineData(1.1, 0.1, 1.1)] + [InlineData(1.1, 1.2, 1.2)] + [InlineData(0.01, 0.02, 0.02)] + [InlineData(-0.01, -0.02, -0.01)] + public void BigDecimalMaxShouldProduceExpectedResult(double left, double right, double expected) + { + // When + BigDecimal actual = BigDecimal.Max(left, right); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BigDecimal.MinMax should produce the expected result")] + [InlineData(0, 0, 0, 0)] + [InlineData(1, 0, 0, 1)] + [InlineData(1, 1, 1, 1)] + [InlineData(1.1, 0.1, 0.1, 1.1)] + [InlineData(1.1, 1.2, 1.1, 1.2)] + [InlineData(0.01, 0.02, 0.01, 0.02)] + [InlineData(-0.01, -0.02, -0.02, -0.01)] + public void BigDecimalMinMaxShouldProduceExpectedResult(double left, double right, double expectedMin, double expectedMax) + { + // When + (BigDecimal actualMin, BigDecimal actualMax) = BigDecimal.MinMax(left, right); + + // Then + Assert.Equal(expectedMin, actualMin); + Assert.Equal(expectedMax, actualMax); + } + + [Theory(DisplayName = "BigDecimal.MinMagnitude should produce expected result")] + [InlineData(0, 0, 0)] + [InlineData(0, 1, 0)] + [InlineData(0, -1, 0)] + [InlineData(-1, 1, -1)] + [InlineData(1, 2, 1)] + [InlineData(1, -2, 1)] + [InlineData(-1, 2, -1)] + [InlineData(-1, -2, -1)] + [InlineData(123.456, 456.789, 123.456)] + [InlineData(-123.456, 456.789, -123.456)] + [InlineData(123.456, -456.789, 123.456)] + [InlineData(-123.456, -456.789, -123.456)] + [InlineData(0.1, 0.01, 0.01)] + [InlineData(0.1, -0.01, -0.01)] + [InlineData(-0.1, 0.01, 0.01)] + [InlineData(-0.1, -0.01, -0.01)] + public void BigDecimalMinMagnitudeShouldProduceExpectedResult(double left, double right, double expected) + { + // When + BigDecimal actual = BigDecimal.MinMagnitude(left, right); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BigDecimal.MaxMagnitude should produce expected result")] + [InlineData(0, 0, 0)] + [InlineData(0, 1, 1)] + [InlineData(0, -1, -1)] + [InlineData(-1, 1, 1)] + [InlineData(1, 2, 2)] + [InlineData(1, -2, -2)] + [InlineData(-1, 2, 2)] + [InlineData(-1, -2, -2)] + [InlineData(123.456, 456.789, 456.789)] + [InlineData(-123.456, 456.789, 456.789)] + [InlineData(123.456, -456.789, -456.789)] + [InlineData(-123.456, -456.789, -456.789)] + [InlineData(0.1, 0.01, 0.1)] + [InlineData(0.1, -0.01, 0.1)] + [InlineData(-0.1, 0.01, -0.1)] + [InlineData(-0.1, -0.01, -0.1)] + public void BigDecimalMaxMagnitudeShouldProduceExpectedResult(double left, double right, double expected) + { + // When + BigDecimal actual = BigDecimal.MaxMagnitude(left, right); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BigDecimal.MinScale should produce the expected result")] + [InlineData(0, 0, 0)] + [InlineData(0.1, 0, 0)] + [InlineData(0.01, 0.1, 1)] + [InlineData(0.001, 0.01, 2)] + public void BigDecimalMinScaleShouldProduceExpectedResult(double left, double right, double expected) + { + // When + BigDecimal actual = BigDecimal.MinScale(left, right); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BigDecimal.MaxScale should produce the expected result")] + [InlineData(0, 0, 0)] + [InlineData(0.1, 0, 1)] + [InlineData(0.01, 0.1, 2)] + [InlineData(0.001, 0.01, 3)] + public void BigDecimalMaxScaleShouldProduceExpectedResult(double left, double right, double expected) + { + // When + BigDecimal actual = BigDecimal.MaxScale(left, right); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BigDecimal.MinScaleMaxScale should produce the expected result")] + [InlineData(0, 0, 0, 0)] + [InlineData(0.1, 0, 0, 1)] + [InlineData(0.01, 0.1, 1, 2)] + [InlineData(0.001, 0.01, 2, 3)] + public void BigDecimalMinScaleMaxScaleShouldProduceExpectedResult(double left, double right, double expectedMin, double expectedMax) + { + // When + (BigDecimal actualMin, BigDecimal actualMax) = BigDecimal.MinMaxScale(left, right); + + // Then + Assert.Equal(expectedMin, actualMin); + Assert.Equal(expectedMax, actualMax); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstantTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstantTests.cs new file mode 100644 index 0000000..aa99386 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstantTests.cs @@ -0,0 +1,134 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstantTests +{ + [Fact(DisplayName = "BigDecimal.NegativeOne should produce the expected result")] + public void BigDecimalNegativeOneShouldProduceExpectedResult() + { + // Given + const int expectedUnscaledValue = -1; + const int expectedScale = 0; + + // When + BigDecimal actual = BigDecimal.NegativeOne; + + // Then + Assert.Equal(expectedUnscaledValue, actual.UnscaledValue); + Assert.Equal(expectedScale, actual.Scale); + } + + [Fact(DisplayName = "BigDecimal.Zero should produce the expected result")] + public void BigDecimalZeroShouldProduceExpectedResult() + { + // Given + const int expectedUnscaledValue = 0; + const int expectedScale = 0; + + // When + BigDecimal actual = BigDecimal.Zero; + + // Then + Assert.Equal(expectedUnscaledValue, actual.UnscaledValue); + Assert.Equal(expectedScale, actual.Scale); + } + + [Fact(DisplayName = "BigDecimal.One should produce the expected result")] + public void BigDecimalOneShouldProduceExpectedResult() + { + // Given + const int expectedUnscaledValue = 1; + const int expectedScale = 0; + + // When + BigDecimal actual = BigDecimal.One; + + // Then + Assert.Equal(expectedUnscaledValue, actual.UnscaledValue); + Assert.Equal(expectedScale, actual.Scale); + } + + [Fact(DisplayName = "BigDecimal.Two should produce the expected result")] + public void BigDecimalTwoShouldProduceExpectedResult() + { + // Given + const int expectedUnscaledValue = 2; + const int expectedScale = 0; + + // When + BigDecimal actual = BigDecimal.Two; + + // Then + Assert.Equal(expectedUnscaledValue, actual.UnscaledValue); + Assert.Equal(expectedScale, actual.Scale); + } + + [Fact(DisplayName = "BigDecimal.Ten should produce the expected result")] + public void BigDecimalTenShouldProduceExpectedResult() + { + // Given + const int expectedUnscaledValue = 10; + const int expectedScale = 0; + + // When + BigDecimal actual = BigDecimal.Ten; + + // Then + Assert.Equal(expectedUnscaledValue, actual.UnscaledValue); + Assert.Equal(expectedScale, actual.Scale); + } + + [Fact(DisplayName = "BigDecimal.E should produce the expected result")] + public void BigDecimalEShouldProduceExpectedResult() + { + // Given + const string expected = "2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354"; + + // When + BigDecimal actual = BigDecimal.E; + + // Then + Assert.Equal(expected, actual.ToString()); + } + + [Fact(DisplayName = "BigDecimal.Pi should produce the expected result")] + public void BigDecimalPiShouldProduceExpectedResult() + { + // Given + const string expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"; + + // When + BigDecimal actual = BigDecimal.Pi; + + // Then + Assert.Equal(expected, actual.ToString()); + } + + [Fact(DisplayName = "BigDecimal.Tau should produce the expected result")] + public void BigDecimalTauShouldProduceExpectedResult() + { + // Given + const string expected = "6.2831853071795864769252867665590057683943387987502116419498891846156328125724179972560696506842341359642961730265646132941876892191011644634507188162569622349005682054038770422111192892458979098607639288576219513318668922569512964675735663305424038182912971338469206972209086532964267872145204982825474491740132126311763497630418419256585081834307287357851807200226610610976409330427682939038830232188661145407315191839061843722347638652235862102370961489247599254991347037715054497824558763660238982596673467248813132861720427898927904494743814043597218874055410784343525863535047693496369353388102640011362542905271216555715426855155792183472743574429368818024499068602930991707421015845593785178470840399122242580439217280688363196272595495426199210374144226999999967459560999021194634656321926371900489189106938166052850446165066893700705238623763420200062756775057731750664167628412343553382946071965069808575109374623191257277647075751875039155637155610643424536132260038557532223918184328403979"; + + // When + BigDecimal actual = BigDecimal.Tau; + + // Then + Assert.Equal(expected, actual.ToString()); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorBigIntegerTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorBigIntegerTests.cs new file mode 100644 index 0000000..93699e7 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorBigIntegerTests.cs @@ -0,0 +1,76 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorBigIntegerTests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled BigInteger value and scale (fractional scaling)")] + [InlineData(0, 0)] + [InlineData(1, 0)] + [InlineData(1, 1)] + [InlineData(1, 2)] + [InlineData(1, 10)] + [InlineData(-1, 0)] + [InlineData(-1, 1)] + [InlineData(-1, 2)] + [InlineData(-1, 10)] + [InlineData(10, 0)] + [InlineData(10, 1)] + [InlineData(10, 2)] + [InlineData(10, 10)] + [InlineData(-10, 0)] + [InlineData(-10, 1)] + [InlineData(-10, 2)] + [InlineData(-10, 10)] + public void BigDecimalShouldBeConstructableFromUnscaledValueAndScaleWithFractionalScaling(long unscaledValue, int scale) + { + // When + BigDecimal value = unscaledValue.ToBigInteger().ToBigDecimal(scale, ScaleMode.Fractional); + + // Then + Assert.Equal(unscaledValue, value.ToNumberInfo().UnscaledValue); + Assert.Equal(scale, value.ToNumberInfo().Scale); + } + + [Theory(DisplayName = "BigDecimal should be constructable from unscaled BigInteger value and scale (Integral Scaling)")] + [InlineData(0, 0, 0)] + [InlineData(1, 0, 1)] + [InlineData(1, 1, 10)] + [InlineData(1, 2, 100)] + [InlineData(1, 10, 10000000000)] + [InlineData(-1, 0, -1)] + [InlineData(-1, 1, -10)] + [InlineData(-1, 2, -100)] + [InlineData(-1, 10, -10000000000)] + [InlineData(10, 0, 10)] + [InlineData(10, 1, 100)] + [InlineData(10, 2, 1000)] + [InlineData(10, 10, 100000000000)] + [InlineData(-10, 0, -10)] + [InlineData(-10, 1, -100)] + [InlineData(-10, 2, -1000)] + [InlineData(-10, 10, -100000000000)] + public void BigDecimalShouldBeConstructableFromUnscaledValueAndScaleUsingIntegralScaling(long unscaledValue, int scale, long expected) + { + // When + BigDecimal value = unscaledValue.ToBigInteger().ToBigDecimal(scale); + + // Then + Assert.Equal(expected, value.ToNumberInfo().UnscaledValue); + Assert.Equal(scale, value.ToNumberInfo().Scale); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorByteTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorByteTests.cs new file mode 100644 index 0000000..1412c1b --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorByteTests.cs @@ -0,0 +1,59 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public class BigDecimalConstructorByteTests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled byte value and scale (fractional scaling)")] + [InlineData(byte.MaxValue, 0, "255")] + [InlineData(byte.MaxValue, 1, "25.5")] + [InlineData(byte.MaxValue, 2, "2.55")] + [InlineData(byte.MaxValue, 3, "0.255")] + [InlineData(byte.MaxValue, 4, "0.0255")] + [InlineData(byte.MaxValue, 5, "0.00255")] + [InlineData(byte.MaxValue, 6, "0.000255")] + [InlineData(byte.MaxValue, 7, "0.0000255")] + [InlineData(byte.MaxValue, 8, "0.00000255")] + [InlineData(byte.MaxValue, 9, "0.000000255")] + [InlineData(byte.MaxValue, 10, "0.0000000255")] + [InlineData(byte.MaxValue, 20, "0.00000000000000000255")] + [InlineData(byte.MinValue, 0, "0")] + [InlineData(byte.MinValue, 1, "0.0")] + [InlineData(byte.MinValue, 2, "0.00")] + [InlineData(byte.MinValue, 3, "0.000")] + [InlineData(byte.MinValue, 4, "0.0000")] + [InlineData(byte.MinValue, 5, "0.00000")] + [InlineData(byte.MinValue, 6, "0.000000")] + [InlineData(byte.MinValue, 7, "0.0000000")] + [InlineData(byte.MinValue, 8, "0.00000000")] + [InlineData(byte.MinValue, 9, "0.000000000")] + [InlineData(byte.MinValue, 10, "0.0000000000")] + [InlineData(byte.MinValue, 20, "0.00000000000000000000")] + public void BigDecimalShouldBeConstructableFromUnscaledByteValueAndScaleWithFractionalScaling(byte value, int scale, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(scale, ScaleMode.Fractional); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorDoubleBinaryTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorDoubleBinaryTests.cs new file mode 100644 index 0000000..08948eb --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorDoubleBinaryTests.cs @@ -0,0 +1,37 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorDoubleBinaryTests +{ + [BigDecimalIeee754BinaryData] + [Theory(DisplayName = "BigDecimal should be constructable from double value using Binary conversion")] + public void BigDecimalShouldBeConstructableFromDoubleValueUsingBinaryConversion(double value, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(ConversionMode.Binary); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorDoubleDecimalTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorDoubleDecimalTests.cs new file mode 100644 index 0000000..78255ca --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorDoubleDecimalTests.cs @@ -0,0 +1,37 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorDoubleDecimalTests +{ + [BigDecimalIeee754DecimalData] + [Theory(DisplayName = "BigDecimal should be constructable from double value using Decimal conversion")] + public void BigDecimalShouldBeConstructableFromDoubleValueUsingDecimalConversion(double value, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt16Tests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt16Tests.cs new file mode 100644 index 0000000..68a2e60 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt16Tests.cs @@ -0,0 +1,59 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public class BigDecimalConstructorInt16Tests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled Int16 value and scale (fractional scaling)")] + [InlineData(short.MaxValue, 0, "32767")] + [InlineData(short.MaxValue, 1, "3276.7")] + [InlineData(short.MaxValue, 2, "327.67")] + [InlineData(short.MaxValue, 3, "32.767")] + [InlineData(short.MaxValue, 4, "3.2767")] + [InlineData(short.MaxValue, 5, "0.32767")] + [InlineData(short.MaxValue, 6, "0.032767")] + [InlineData(short.MaxValue, 7, "0.0032767")] + [InlineData(short.MaxValue, 8, "0.00032767")] + [InlineData(short.MaxValue, 9, "0.000032767")] + [InlineData(short.MaxValue, 10, "0.0000032767")] + [InlineData(short.MaxValue, 20, "0.00000000000000032767")] + [InlineData(short.MinValue, 0, "-32768")] + [InlineData(short.MinValue, 1, "-3276.8")] + [InlineData(short.MinValue, 2, "-327.68")] + [InlineData(short.MinValue, 3, "-32.768")] + [InlineData(short.MinValue, 4, "-3.2768")] + [InlineData(short.MinValue, 5, "-0.32768")] + [InlineData(short.MinValue, 6, "-0.032768")] + [InlineData(short.MinValue, 7, "-0.0032768")] + [InlineData(short.MinValue, 8, "-0.00032768")] + [InlineData(short.MinValue, 9, "-0.000032768")] + [InlineData(short.MinValue, 10, "-0.0000032768")] + [InlineData(short.MinValue, 20, "-0.00000000000000032768")] + public void BigDecimalShouldBeConstructableFromUnscaledInt16ValueAndScaleWithFractionalScaling(short value, int scale, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(scale, ScaleMode.Fractional); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt32Tests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt32Tests.cs new file mode 100644 index 0000000..07c0395 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt32Tests.cs @@ -0,0 +1,83 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorInt32Tests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled Int32 value and scale (fractional scaling)")] + [InlineData(1, 0, "1")] + [InlineData(1, 1, "0.1")] + [InlineData(1, 2, "0.01")] + [InlineData(1, 3, "0.001")] + [InlineData(1, 4, "0.0001")] + [InlineData(1, 5, "0.00001")] + [InlineData(1, 6, "0.000001")] + [InlineData(1, 7, "0.0000001")] + [InlineData(1, 8, "0.00000001")] + [InlineData(1, 9, "0.000000001")] + [InlineData(1, 10, "0.0000000001")] + [InlineData(1, 20, "0.00000000000000000001")] + [InlineData(-1, 0, "-1")] + [InlineData(-1, 1, "-0.1")] + [InlineData(-1, 2, "-0.01")] + [InlineData(-1, 3, "-0.001")] + [InlineData(-1, 4, "-0.0001")] + [InlineData(-1, 5, "-0.00001")] + [InlineData(-1, 6, "-0.000001")] + [InlineData(-1, 7, "-0.0000001")] + [InlineData(-1, 8, "-0.00000001")] + [InlineData(-1, 9, "-0.000000001")] + [InlineData(-1, 10, "-0.0000000001")] + [InlineData(-1, 20, "-0.00000000000000000001")] + [InlineData(int.MaxValue, 0, "2147483647")] + [InlineData(int.MaxValue, 1, "214748364.7")] + [InlineData(int.MaxValue, 2, "21474836.47")] + [InlineData(int.MaxValue, 3, "2147483.647")] + [InlineData(int.MaxValue, 4, "214748.3647")] + [InlineData(int.MaxValue, 5, "21474.83647")] + [InlineData(int.MaxValue, 6, "2147.483647")] + [InlineData(int.MaxValue, 7, "214.7483647")] + [InlineData(int.MaxValue, 8, "21.47483647")] + [InlineData(int.MaxValue, 9, "2.147483647")] + [InlineData(int.MaxValue, 10, "0.2147483647")] + [InlineData(int.MaxValue, 20, "0.00000000002147483647")] + [InlineData(int.MinValue, 0, "-2147483648")] + [InlineData(int.MinValue, 1, "-214748364.8")] + [InlineData(int.MinValue, 2, "-21474836.48")] + [InlineData(int.MinValue, 3, "-2147483.648")] + [InlineData(int.MinValue, 4, "-214748.3648")] + [InlineData(int.MinValue, 5, "-21474.83648")] + [InlineData(int.MinValue, 6, "-2147.483648")] + [InlineData(int.MinValue, 7, "-214.7483648")] + [InlineData(int.MinValue, 8, "-21.47483648")] + [InlineData(int.MinValue, 9, "-2.147483648")] + [InlineData(int.MinValue, 10, "-0.2147483648")] + [InlineData(int.MinValue, 20, "-0.00000000002147483648")] + public void BigDecimalShouldBeConstructableFromUnscaledInt32ValueAndScaleWithFractionalScaling(int value, int scale, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(scale, ScaleMode.Fractional); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt64Tests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt64Tests.cs new file mode 100644 index 0000000..bc1c254 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorInt64Tests.cs @@ -0,0 +1,59 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorInt64Tests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled Int64 value and scale (fractional scaling)")] + [InlineData(long.MaxValue, 0, "9223372036854775807")] + [InlineData(long.MaxValue, 1, "922337203685477580.7")] + [InlineData(long.MaxValue, 2, "92233720368547758.07")] + [InlineData(long.MaxValue, 3, "9223372036854775.807")] + [InlineData(long.MaxValue, 4, "922337203685477.5807")] + [InlineData(long.MaxValue, 5, "92233720368547.75807")] + [InlineData(long.MaxValue, 6, "9223372036854.775807")] + [InlineData(long.MaxValue, 7, "922337203685.4775807")] + [InlineData(long.MaxValue, 8, "92233720368.54775807")] + [InlineData(long.MaxValue, 9, "9223372036.854775807")] + [InlineData(long.MaxValue, 10, "922337203.6854775807")] + [InlineData(long.MaxValue, 20, "0.09223372036854775807")] + [InlineData(long.MinValue, 0, "-9223372036854775808")] + [InlineData(long.MinValue, 1, "-922337203685477580.8")] + [InlineData(long.MinValue, 2, "-92233720368547758.08")] + [InlineData(long.MinValue, 3, "-9223372036854775.808")] + [InlineData(long.MinValue, 4, "-922337203685477.5808")] + [InlineData(long.MinValue, 5, "-92233720368547.75808")] + [InlineData(long.MinValue, 6, "-9223372036854.775808")] + [InlineData(long.MinValue, 7, "-922337203685.4775808")] + [InlineData(long.MinValue, 8, "-92233720368.54775808")] + [InlineData(long.MinValue, 9, "-9223372036.854775808")] + [InlineData(long.MinValue, 10, "-922337203.6854775808")] + [InlineData(long.MinValue, 20, "-0.09223372036854775808")] + public void BigDecimalShouldBeConstructableFromUnscaledInt64ValueAndScaleWithFractionalScaling(long value, int scale, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(scale, ScaleMode.Fractional); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorSByteTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorSByteTests.cs new file mode 100644 index 0000000..7ea0eb1 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorSByteTests.cs @@ -0,0 +1,59 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorSByteTests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled sbyte value and scale (fractional scaling)")] + [InlineData(sbyte.MaxValue, 0, "127")] + [InlineData(sbyte.MaxValue, 1, "12.7")] + [InlineData(sbyte.MaxValue, 2, "1.27")] + [InlineData(sbyte.MaxValue, 3, "0.127")] + [InlineData(sbyte.MaxValue, 4, "0.0127")] + [InlineData(sbyte.MaxValue, 5, "0.00127")] + [InlineData(sbyte.MaxValue, 6, "0.000127")] + [InlineData(sbyte.MaxValue, 7, "0.0000127")] + [InlineData(sbyte.MaxValue, 8, "0.00000127")] + [InlineData(sbyte.MaxValue, 9, "0.000000127")] + [InlineData(sbyte.MaxValue, 10, "0.0000000127")] + [InlineData(sbyte.MaxValue, 20, "0.00000000000000000127")] + [InlineData(sbyte.MinValue, 0, "-128")] + [InlineData(sbyte.MinValue, 1, "-12.8")] + [InlineData(sbyte.MinValue, 2, "-1.28")] + [InlineData(sbyte.MinValue, 3, "-0.128")] + [InlineData(sbyte.MinValue, 4, "-0.0128")] + [InlineData(sbyte.MinValue, 5, "-0.00128")] + [InlineData(sbyte.MinValue, 6, "-0.000128")] + [InlineData(sbyte.MinValue, 7, "-0.0000128")] + [InlineData(sbyte.MinValue, 8, "-0.00000128")] + [InlineData(sbyte.MinValue, 9, "-0.000000128")] + [InlineData(sbyte.MinValue, 10, "-0.0000000128")] + [InlineData(sbyte.MinValue, 20, "-0.00000000000000000128")] + public void BigDecimalShouldBeConstructableFromUnscaledSByteValueAndScaleWithFractionalScaling(sbyte value, int scale, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(scale, ScaleMode.Fractional); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt16Tests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt16Tests.cs new file mode 100644 index 0000000..9e61076 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt16Tests.cs @@ -0,0 +1,59 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorUInt16Tests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled UInt16 value and scale (fractional scaling)")] + [InlineData(ushort.MaxValue, 0, "65535")] + [InlineData(ushort.MaxValue, 1, "6553.5")] + [InlineData(ushort.MaxValue, 2, "655.35")] + [InlineData(ushort.MaxValue, 3, "65.535")] + [InlineData(ushort.MaxValue, 4, "6.5535")] + [InlineData(ushort.MaxValue, 5, "0.65535")] + [InlineData(ushort.MaxValue, 6, "0.065535")] + [InlineData(ushort.MaxValue, 7, "0.0065535")] + [InlineData(ushort.MaxValue, 8, "0.00065535")] + [InlineData(ushort.MaxValue, 9, "0.000065535")] + [InlineData(ushort.MaxValue, 10, "0.0000065535")] + [InlineData(ushort.MaxValue, 20, "0.00000000000000065535")] + [InlineData(ushort.MinValue, 0, "0")] + [InlineData(ushort.MinValue, 1, "0.0")] + [InlineData(ushort.MinValue, 2, "0.00")] + [InlineData(ushort.MinValue, 3, "0.000")] + [InlineData(ushort.MinValue, 4, "0.0000")] + [InlineData(ushort.MinValue, 5, "0.00000")] + [InlineData(ushort.MinValue, 6, "0.000000")] + [InlineData(ushort.MinValue, 7, "0.0000000")] + [InlineData(ushort.MinValue, 8, "0.00000000")] + [InlineData(ushort.MinValue, 9, "0.000000000")] + [InlineData(ushort.MinValue, 10, "0.0000000000")] + [InlineData(ushort.MinValue, 20, "0.00000000000000000000")] + public void BigDecimalShouldBeConstructableFromUnscaledUInt16ValueAndScaleWithFractionalScaling(ushort value, int scale, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(scale, ScaleMode.Fractional); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt32Tests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt32Tests.cs new file mode 100644 index 0000000..6a70a9c --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt32Tests.cs @@ -0,0 +1,59 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorUInt32Tests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled UInt32 value and scale (fractional scaling)")] + [InlineData(uint.MaxValue, 0, "4294967295")] + [InlineData(uint.MaxValue, 1, "429496729.5")] + [InlineData(uint.MaxValue, 2, "42949672.95")] + [InlineData(uint.MaxValue, 3, "4294967.295")] + [InlineData(uint.MaxValue, 4, "429496.7295")] + [InlineData(uint.MaxValue, 5, "42949.67295")] + [InlineData(uint.MaxValue, 6, "4294.967295")] + [InlineData(uint.MaxValue, 7, "429.4967295")] + [InlineData(uint.MaxValue, 8, "42.94967295")] + [InlineData(uint.MaxValue, 9, "4.294967295")] + [InlineData(uint.MaxValue, 10, "0.4294967295")] + [InlineData(uint.MaxValue, 20, "0.00000000004294967295")] + [InlineData(uint.MinValue, 0, "0")] + [InlineData(uint.MinValue, 1, "0.0")] + [InlineData(uint.MinValue, 2, "0.00")] + [InlineData(uint.MinValue, 3, "0.000")] + [InlineData(uint.MinValue, 4, "0.0000")] + [InlineData(uint.MinValue, 5, "0.00000")] + [InlineData(uint.MinValue, 6, "0.000000")] + [InlineData(uint.MinValue, 7, "0.0000000")] + [InlineData(uint.MinValue, 8, "0.00000000")] + [InlineData(uint.MinValue, 9, "0.000000000")] + [InlineData(uint.MinValue, 10, "0.0000000000")] + [InlineData(uint.MinValue, 20, "0.00000000000000000000")] + public void BigDecimalShouldBeConstructableFromUnscaledUInt32ValueAndScaleWithFractionalScaling(uint value, int scale, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(scale, ScaleMode.Fractional); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt64Tests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt64Tests.cs new file mode 100644 index 0000000..b6ce6c1 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalConstructorUInt64Tests.cs @@ -0,0 +1,59 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalConstructorUInt64Tests +{ + [Theory(DisplayName = "BigDecimal should be constructable from unscaled UInt64 value and scale (fractional scaling)")] + [InlineData(ulong.MaxValue, 0, "18446744073709551615")] + [InlineData(ulong.MaxValue, 1, "1844674407370955161.5")] + [InlineData(ulong.MaxValue, 2, "184467440737095516.15")] + [InlineData(ulong.MaxValue, 3, "18446744073709551.615")] + [InlineData(ulong.MaxValue, 4, "1844674407370955.1615")] + [InlineData(ulong.MaxValue, 5, "184467440737095.51615")] + [InlineData(ulong.MaxValue, 6, "18446744073709.551615")] + [InlineData(ulong.MaxValue, 7, "1844674407370.9551615")] + [InlineData(ulong.MaxValue, 8, "184467440737.09551615")] + [InlineData(ulong.MaxValue, 9, "18446744073.709551615")] + [InlineData(ulong.MaxValue, 10, "1844674407.3709551615")] + [InlineData(ulong.MaxValue, 20, "0.18446744073709551615")] + [InlineData(ulong.MinValue, 0, "0")] + [InlineData(ulong.MinValue, 1, "0.0")] + [InlineData(ulong.MinValue, 2, "0.00")] + [InlineData(ulong.MinValue, 3, "0.000")] + [InlineData(ulong.MinValue, 4, "0.0000")] + [InlineData(ulong.MinValue, 5, "0.00000")] + [InlineData(ulong.MinValue, 6, "0.000000")] + [InlineData(ulong.MinValue, 7, "0.0000000")] + [InlineData(ulong.MinValue, 8, "0.00000000")] + [InlineData(ulong.MinValue, 9, "0.000000000")] + [InlineData(ulong.MinValue, 10, "0.0000000000")] + [InlineData(ulong.MinValue, 20, "0.00000000000000000000")] + public void BigDecimalShouldBeConstructableFromUnscaledUInt64ValueAndScaleWithFractionalScaling(ulong value, int scale, string expected) + { + // Given + BigDecimal candidate = value.ToBigDecimal(scale, ScaleMode.Fractional); + CultureInfo culture = CultureInfo.GetCultureInfo("en-GB"); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalEqualityComparerTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalEqualityComparerTests.cs new file mode 100644 index 0000000..757cfca --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalEqualityComparerTests.cs @@ -0,0 +1,57 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalEqualityComparerTests +{ + [NumberInfoEqualityComparerData] + [Theory(DisplayName = "BigDecimalEqualityComparer.Equals should produce the expected result (Strict)")] + public void BigDecimalEqualityComparerEqualsShouldProduceExpectedResultStrict(decimal left, decimal right, Guid _) + { + // Given + bool expected = left == right && left.Scale == right.Scale; + BigDecimal leftCandidate = left.ToBigDecimal(); + BigDecimal rightCandidate = right.ToBigDecimal(); + + // When + bool actualFromComparer = BigDecimalEqualityComparer.Strict.Equals(leftCandidate, rightCandidate); + bool actualFromBigDecimal = leftCandidate.Equals(rightCandidate); + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromBigDecimal); + } + + [NumberInfoEqualityComparerData] + [Theory(DisplayName = "BigDecimalEqualityComparer.Equals should produce the expected result (Semantic)")] + public void BigDecimalEqualityComparerEqualsShouldProduceExpectedResultSemantic(decimal left, decimal right, Guid _) + { + // Given + bool expected = left == right; + BigDecimal leftCandidate = left.ToBigDecimal(); + BigDecimal rightCandidate = right.ToBigDecimal(); + + // When + bool actualFromComparer = BigDecimalEqualityComparer.Semantic.Equals(leftCandidate, rightCandidate); + bool actualFromBigDecimal = leftCandidate == rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromBigDecimal); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalFormatTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalFormatTests.cs new file mode 100644 index 0000000..388556a --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalFormatTests.cs @@ -0,0 +1,97 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalFormatTests +{ + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Format should produce the expected result (Currency)")] + public void BigDecimalFormatShouldProduceExpectedResultCurrency(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = string.Create(culture, $"{value:C}"); + BigDecimal candidate = value; + + // When + string actual = string.Create(culture, $"{candidate:C}"); + + // Then + Assert.Equal(expected, actual); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Format should produce the expected result (Fixed)")] + public void BigDecimalFormatShouldProduceExpectedResultFixed(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = string.Create(culture, $"{value:F}"); + BigDecimal candidate = value; + + // When + string actual = string.Create(culture, $"{candidate:F}"); + + // Then + Assert.Equal(expected, actual); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Format should produce the expected result (General)")] + public void BigDecimalFormatShouldProduceExpectedResultGeneral(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = string.Create(culture, $"{value:G}"); + BigDecimal candidate = value; + + // When + string actual = string.Create(culture, $"{candidate:G}"); + + // Then + Assert.Equal(expected, actual); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Format should produce the expected result (Number)")] + public void BigDecimalFormatShouldProduceExpectedResultNumber(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = string.Create(culture, $"{value:N}"); + BigDecimal candidate = value; + + // When + string actual = string.Create(culture, $"{candidate:N}"); + + // Then + Assert.Equal(expected, actual); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Format should produce the expected result (Percent)")] + public void BigDecimalFormatShouldProduceExpectedResultPercent(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = string.Create(culture, $"{value:P}"); + BigDecimal candidate = value; + + // When + string actual = string.Create(culture, $"{candidate:P}"); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalIsTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalIsTests.cs new file mode 100644 index 0000000..4ecbf3c --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalIsTests.cs @@ -0,0 +1,105 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalIsTests +{ + [BigDecimalIsData] + [Theory(DisplayName = "BigDecimal.IsInteger should produce the expected result")] + public void BigDecimalIsIntegerShouldProduceExpectedResult(decimal value, Guid _) + { + // Given + bool expected = decimal.IsInteger(value); + + // When + bool actual = BigDecimal.IsInteger(value); + + // Then + Assert.Equal(expected, actual); + } + + [BigDecimalIsData] + [Theory(DisplayName = "BigDecimal.IsEvenInteger should produce the expected result")] + public void BigDecimalIsEvenIntegerShouldProduceExpectedResult(decimal value, Guid _) + { + // Given + bool expected = decimal.IsEvenInteger(value); + + // When + bool actual = BigDecimal.IsEvenInteger(value); + + // Then + Assert.Equal(expected, actual); + } + + [BigDecimalIsData] + [Theory(DisplayName = "BigDecimal.IsOddInteger should produce the expected result")] + public void BigDecimalIsOddIntegerShouldProduceExpectedResult(decimal value, Guid _) + { + // Given + bool expected = decimal.IsOddInteger(value); + + // When + bool actual = BigDecimal.IsOddInteger(value); + + // Then + Assert.Equal(expected, actual); + } + + [BigDecimalIsData] + [Theory(DisplayName = "BigDecimal.IsNegative should produce the expected result")] + public void BigDecimalIsNegativeShouldProduceExpectedResult(decimal value, Guid _) + { + // Given + bool expected = decimal.IsNegative(value); + + // When + bool actual = BigDecimal.IsNegative(value); + + // Then + Assert.Equal(expected, actual); + } + + [BigDecimalIsData] + [Theory(DisplayName = "BigDecimal.IsPositive should produce the expected result")] + public void BigDecimalIsPositiveShouldProduceExpectedResult(decimal value, Guid _) + { + // Given + bool expected = decimal.IsPositive(value); + + // When + bool actual = BigDecimal.IsPositive(value); + + // Then + Assert.Equal(expected, actual); + } + + [BigDecimalIsData] + [Theory(DisplayName = "BigDecimal.IsZero should produce the expected result")] + public void BigDecimalIsZeroShouldProduceExpectedResult(decimal value, Guid _) + { + // Given + bool expected = value is 0; + + // When + bool actual = BigDecimal.IsZero(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalOrdinalityComparerTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalOrdinalityComparerTests.cs new file mode 100644 index 0000000..91f1f04 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalOrdinalityComparerTests.cs @@ -0,0 +1,129 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalOrdinalityComparerTests +{ + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "BigDecimalOrdinalityComparer.Compare should produce the expected result")] + public void BigDecimalOrdinalityComparerCompareShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + int expected = left.CompareTo(right); + BigDecimal leftCandidate = left.ToBigDecimal(); + BigDecimal rightCandidate = right.ToBigDecimal(); + + // When + int actualFromComparer = BigDecimalOrdinalityComparer.Default.Compare(leftCandidate, rightCandidate); + int actualFromBigDecimal = leftCandidate.CompareTo(rightCandidate); + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromBigDecimal); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "BigDecimalOrdinalityComparer.IsEqual should produce the expected result")] + public void BigDecimalOrdinalityComparerIsEqualShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left.CompareTo(right) is 0; + BigDecimal leftCandidate = left.ToBigDecimal(); + BigDecimal rightCandidate = right.ToBigDecimal(); + + // When + bool actualFromComparer = BigDecimalOrdinalityComparer.Default.IsEqual(leftCandidate, rightCandidate); + bool actualFromBigDecimal = leftCandidate.CompareTo(rightCandidate) is 0; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromBigDecimal); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "BigDecimalOrdinalityComparer.IsGreaterThan should produce the expected result")] + public void BigDecimalOrdinalityComparerIsGreaterThanShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left > right; + BigDecimal leftCandidate = left.ToBigDecimal(); + BigDecimal rightCandidate = right.ToBigDecimal(); + + // When + bool actualFromComparer = BigDecimalOrdinalityComparer.Default.IsGreaterThan(leftCandidate, rightCandidate); + bool actualFromBigDecimal = leftCandidate > rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromBigDecimal); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "BigDecimalOrdinalityComparer.IsGreaterThanOrEqual should produce the expected result")] + public void BigDecimalOrdinalityComparerIsGreaterOrEqualThanShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left >= right; + BigDecimal leftCandidate = left.ToBigDecimal(); + BigDecimal rightCandidate = right.ToBigDecimal(); + + // When + bool actualFromComparer = BigDecimalOrdinalityComparer.Default.IsGreaterThanOrEqual(leftCandidate, rightCandidate); + bool actualFromBigDecimal = leftCandidate >= rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromBigDecimal); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "BigDecimalOrdinalityComparer.IsLessThan should produce the expected result")] + public void BigDecimalOrdinalityComparerIsLessThanShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left < right; + BigDecimal leftCandidate = left.ToBigDecimal(); + BigDecimal rightCandidate = right.ToBigDecimal(); + + // When + bool actualFromComparer = BigDecimalOrdinalityComparer.Default.IsLessThan(leftCandidate, rightCandidate); + bool actualFromBigDecimal = leftCandidate < rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromBigDecimal); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "BigDecimalOrdinalityComparer.IsLessThanOrEqual should produce the expected result")] + public void BigDecimalOrdinalityComparerIsLessOrEqualThanShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left <= right; + BigDecimal leftCandidate = left.ToBigDecimal(); + BigDecimal rightCandidate = right.ToBigDecimal(); + + // When + bool actualFromComparer = BigDecimalOrdinalityComparer.Default.IsLessThanOrEqual(leftCandidate, rightCandidate); + bool actualFromBigDecimal = leftCandidate <= rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromBigDecimal); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalParseTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalParseTests.cs new file mode 100644 index 0000000..ddb774a --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalParseTests.cs @@ -0,0 +1,96 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalParseTests +{ + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Parse should produce the expected result (Currency)")] + public void BigDecimalParseShouldProduceExpectedResultCurrency(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToString("C", culture); + decimal expected = decimal.Parse(formatted, NumberStyles.Currency, culture); + + // When + BigDecimal actual = BigDecimal.Parse(formatted, NumberStyles.Currency, culture); + + // Then + Assert.Equal(expected, actual, BigDecimalEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Parse should produce the expected result (Decimal)")] + public void BigDecimalParseShouldProduceExpectedResultDecimal(decimal expected, CultureInfo culture, Guid _) + { + // Given + string formatted = expected.ToBigDecimal().ToString("D", culture); + + // When + BigDecimal actual = BigDecimal.Parse(formatted, NumberStyles.Number, culture); + + // Then + Assert.Equal(expected, actual, BigDecimalEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Parse should produce the expected result (Fixed)")] + public void BigDecimalParseShouldProduceExpectedResultFixed(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToString("F", culture); + decimal expected = decimal.Parse(formatted, NumberStyles.Float, culture); + + // When + BigDecimal actual = BigDecimal.Parse(formatted, NumberStyles.Float, culture); + + // Then + Assert.Equal(expected, actual, BigDecimalEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Parse should produce the expected result (General)")] + public void BigDecimalParseShouldProduceExpectedResultGeneral(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToString("G", culture); + decimal expected = decimal.Parse(formatted, NumberStyles.Any, culture); + + // When + BigDecimal actual = BigDecimal.Parse(formatted, NumberStyles.Any, culture); + + // Then + Assert.Equal(expected, actual, BigDecimalEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.Parse should produce the expected result (Number)")] + public void BigDecimalParseShouldProduceExpectedResultNumber(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToString("G", culture); + decimal expected = decimal.Parse(formatted, NumberStyles.Number, culture); + + // When + BigDecimal actual = BigDecimal.Parse(formatted, NumberStyles.Number, culture); + + // Then + Assert.Equal(expected, actual, BigDecimalEqualityComparer.Semantic); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalToStringTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalToStringTests.cs new file mode 100644 index 0000000..b8f12c3 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalToStringTests.cs @@ -0,0 +1,97 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalToStringTests +{ + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.ToString should produce the expected result (Currency)")] + public void BigDecimalToStringShouldProduceExpectedResultCurrency(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = value.ToString("C", culture); + BigDecimal candidate = value; + + // When + string actual = candidate.ToString("C", culture); + + // Then + Assert.Equal(expected, actual); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.ToString should produce the expected result (Fixed)")] + public void BigDecimalToStringShouldProduceExpectedResultFixed(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = value.ToString("F", culture); + BigDecimal candidate = value; + + // When + string actual = candidate.ToString("F", culture); + + // Then + Assert.Equal(expected, actual); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.ToString should produce the expected result (General)")] + public void BigDecimalToStringShouldProduceExpectedResultGeneral(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = value.ToString("G", culture); + BigDecimal candidate = value; + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.ToString should produce the expected result (Number)")] + public void BigDecimalToStringShouldProduceExpectedResultNumber(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = value.ToString("N", culture); + BigDecimal candidate = value; + + // When + string actual = candidate.ToString("N", culture); + + // Then + Assert.Equal(expected, actual); + } + + [NumberFormatData] + [Theory(DisplayName = "BigDecimal.ToString should produce the expected result (Percent)")] + public void BigDecimalToStringShouldProduceExpectedResultPercent(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = value.ToString("P", culture); + BigDecimal candidate = value; + + // When + string actual = candidate.ToString("P", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/BigDecimalWriteTests.cs b/OnixLabs.Numerics.UnitTests/BigDecimalWriteTests.cs new file mode 100644 index 0000000..9950022 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/BigDecimalWriteTests.cs @@ -0,0 +1,129 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Buffers.Binary; +using System.Numerics; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class BigDecimalWriteTests +{ + [BigDecimalWriteData] + [Theory(DisplayName = "BigDecimal write significand big endian should produce expected result.")] + public void BigDecimalWriteSignificandBigEndianShouldProduceExpectedResult(decimal value) + { + // Given + NumberInfo info = value.ToBigDecimal().ToNumberInfo(); + byte[] significandBytes = new byte[info.Significand.ToByteArray().Length]; + + // When + ((IFloatingPoint)(BigDecimal)value).WriteSignificandBigEndian(significandBytes); + BigInteger significand = new(significandBytes, isBigEndian: true); + + // Then + Assert.Equal(info.Significand, significand); + } + + [BigDecimalWriteData] + [Theory(DisplayName = "BigDecimal write exponent big endian should produce expected result.")] + public void BigDecimalWriteExponentBigEndianShouldProduceExpectedResult(decimal value) + { + // Given + NumberInfo info = value.ToBigDecimal().ToNumberInfo(); + byte[] exponentBytes = new byte[4]; + + // When + ((IFloatingPoint)(BigDecimal)value).WriteExponentBigEndian(exponentBytes); + int exponent = BinaryPrimitives.ReadInt32BigEndian(exponentBytes); + + // Then + Assert.Equal(info.Exponent, exponent); + } + + [BigDecimalWriteData] + [Theory(DisplayName = "BigDecimal write big endian significand and exponent should produce expected result.")] + public void BigDecimalWriteBigEndianSignificandAndExponentShouldProduceExpectedResult(decimal value) + { + // Given + NumberInfo info = value.ToBigDecimal().ToNumberInfo(); + byte[] significandBytes = new byte[info.Significand.ToByteArray().Length]; + byte[] exponentBytes = new byte[4]; + + // When + ((IFloatingPoint)(BigDecimal)value).WriteSignificandBigEndian(significandBytes); + ((IFloatingPoint)(BigDecimal)value).WriteExponentBigEndian(exponentBytes); + + BigInteger significand = new(significandBytes, isBigEndian: true); + int exponent = BinaryPrimitives.ReadInt32BigEndian(exponentBytes); + + // Then + Assert.Equal(info.Significand, significand); + Assert.Equal(info.Exponent, exponent); + } + + [BigDecimalWriteData] + [Theory(DisplayName = "BigDecimal write significand little endian should produce expected result.")] + public void BigDecimalWriteSignificandLittleEndianShouldProduceExpectedResult(decimal value) + { + // Given + NumberInfo info = value.ToBigDecimal().ToNumberInfo(); + byte[] significandBytes = new byte[info.Significand.ToByteArray().Length]; + + // When + ((IFloatingPoint)(BigDecimal)value).WriteSignificandLittleEndian(significandBytes); + BigInteger significand = new(significandBytes); + + // Then + Assert.Equal(info.Significand, significand); + } + + [BigDecimalWriteData] + [Theory(DisplayName = "BigDecimal write exponent little endian should produce expected result.")] + public void BigDecimalWriteExponentLittleEndianShouldProduceExpectedResult(decimal value) + { + // Given + NumberInfo info = value.ToBigDecimal().ToNumberInfo(); + byte[] exponentBytes = new byte[4]; + + // When + ((IFloatingPoint)(BigDecimal)value).WriteExponentLittleEndian(exponentBytes); + int exponent = BinaryPrimitives.ReadInt32LittleEndian(exponentBytes); + + // Then + Assert.Equal(info.Exponent, exponent); + } + + [BigDecimalWriteData] + [Theory(DisplayName = "BigDecimal write little endian significand and exponent should produce expected result.")] + public void BigDecimalWriteLittleEndianSignificandAndExponentShouldProduceExpectedResult(decimal value) + { + // Given + NumberInfo info = value.ToBigDecimal().ToNumberInfo(); + byte[] significandBytes = new byte[info.Significand.ToByteArray().Length]; + byte[] exponentBytes = new byte[4]; + + // When + ((IFloatingPoint)(BigDecimal)value).WriteSignificandLittleEndian(significandBytes); + ((IFloatingPoint)(BigDecimal)value).WriteExponentLittleEndian(exponentBytes); + + BigInteger significand = new(significandBytes); + int exponent = BinaryPrimitives.ReadInt32LittleEndian(exponentBytes); + + // Then + Assert.Equal(info.Significand, significand); + Assert.Equal(info.Exponent, exponent); + } +} diff --git a/OnixLabs.Numerics.UnitTests/GenericMathDeltaTests.cs b/OnixLabs.Numerics.UnitTests/GenericMathDeltaTests.cs new file mode 100644 index 0000000..db671c3 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/GenericMathDeltaTests.cs @@ -0,0 +1,67 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class GenericMathDeltaTests +{ + [Theory(DisplayName = "GenericMath.Delta should produce the expected result")] + [InlineData(0, 0, 0)] + [InlineData(0, 1, 1)] + [InlineData(0, -1, 1)] + [InlineData(10, 0, 10)] + [InlineData(10, 10, 0)] + [InlineData(10, 9, 1)] + [InlineData(10, 8, 2)] + [InlineData(10, 7, 3)] + [InlineData(10, 6, 4)] + [InlineData(10, 5, 5)] + [InlineData(10, 4, 6)] + [InlineData(10, 3, 7)] + [InlineData(10, 2, 8)] + [InlineData(10, 1, 9)] + [InlineData(-10, 10, 20)] + [InlineData(-10, 9, 19)] + [InlineData(-10, 8, 18)] + [InlineData(-10, 7, 17)] + [InlineData(-10, 6, 16)] + [InlineData(-10, 5, 15)] + [InlineData(-10, 4, 14)] + [InlineData(-10, 3, 13)] + [InlineData(-10, 2, 12)] + [InlineData(-10, 1, 11)] + [InlineData(-10, 0, 10)] + [InlineData(1, 0.1, 0.9)] + [InlineData(1, 0.01, 0.99)] + [InlineData(1, 0.001, 0.999)] + [InlineData(10.125, 0.1, 10.025)] + [InlineData(10.125, 0.01, 10.115)] + [InlineData(10.125, 0.001, 10.124)] + [InlineData(-1, 0.1, 1.1)] + [InlineData(-1, 0.01, 1.01)] + [InlineData(-1, 0.001, 1.001)] + [InlineData(-10.125, 0.1, 10.225)] + [InlineData(-10.125, 0.01, 10.135)] + [InlineData(-10.125, 0.001, 10.126)] + public void GenericMathDeltaShouldProduceExpectedResult(double left, double right, double expected) + { + // When + double actual = GenericMath.Delta(left, right); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/GenericMathIntegerLengthTests.cs b/OnixLabs.Numerics.UnitTests/GenericMathIntegerLengthTests.cs new file mode 100644 index 0000000..b7fb89a --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/GenericMathIntegerLengthTests.cs @@ -0,0 +1,269 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class GenericMathIntegerLengthTests +{ + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (SByte)")] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(10, 2)] + [InlineData(100, 3)] + [InlineData(-1, 1)] + [InlineData(-10, 2)] + [InlineData(-100, 3)] + [InlineData(sbyte.MinValue, 3)] + [InlineData(sbyte.MaxValue, 3)] + public void GenericMathIntegerLengthShouldProduceExpectedResultSByte(sbyte value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (Byte)")] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(10, 2)] + [InlineData(100, 3)] + [InlineData(byte.MinValue, 1)] + [InlineData(byte.MaxValue, 3)] + public void GenericMathIntegerLengthShouldProduceExpectedResultByte(byte value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (Int16)")] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(10, 2)] + [InlineData(100, 3)] + [InlineData(1000, 4)] + [InlineData(10000, 5)] + [InlineData(-1, 1)] + [InlineData(-10, 2)] + [InlineData(-100, 3)] + [InlineData(-1000, 4)] + [InlineData(-10000, 5)] + [InlineData(short.MinValue, 5)] + [InlineData(short.MaxValue, 5)] + public void GenericMathIntegerLengthShouldProduceExpectedResultInt16(short value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (UInt16)")] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(10, 2)] + [InlineData(100, 3)] + [InlineData(1000, 4)] + [InlineData(10000, 5)] + [InlineData(ushort.MinValue, 1)] + [InlineData(ushort.MaxValue, 5)] + public void GenericMathIntegerLengthShouldProduceExpectedResultUInt16(ushort value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (Int32)")] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(10, 2)] + [InlineData(100, 3)] + [InlineData(1000, 4)] + [InlineData(10000, 5)] + [InlineData(100000, 6)] + [InlineData(1000000, 7)] + [InlineData(10000000, 8)] + [InlineData(100000000, 9)] + [InlineData(1000000000, 10)] + [InlineData(-1, 1)] + [InlineData(-10, 2)] + [InlineData(-100, 3)] + [InlineData(-1000, 4)] + [InlineData(-10000, 5)] + [InlineData(-100000, 6)] + [InlineData(-1000000, 7)] + [InlineData(-10000000, 8)] + [InlineData(-100000000, 9)] + [InlineData(-1000000000, 10)] + [InlineData(int.MinValue, 10)] + [InlineData(int.MaxValue, 10)] + public void GenericMathIntegerLengthShouldProduceExpectedResultInt32(int value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (UInt32)")] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(10, 2)] + [InlineData(100, 3)] + [InlineData(1000, 4)] + [InlineData(10000, 5)] + [InlineData(100000, 6)] + [InlineData(1000000, 7)] + [InlineData(10000000, 8)] + [InlineData(100000000, 9)] + [InlineData(1000000000, 10)] + [InlineData(uint.MinValue, 1)] + [InlineData(uint.MaxValue, 10)] + public void GenericMathIntegerLengthShouldProduceExpectedResultUInt32(uint value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (Int64)")] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(10, 2)] + [InlineData(100, 3)] + [InlineData(1000, 4)] + [InlineData(10000, 5)] + [InlineData(100000, 6)] + [InlineData(1000000, 7)] + [InlineData(10000000, 8)] + [InlineData(100000000, 9)] + [InlineData(1000000000, 10)] + [InlineData(10000000000, 11)] + [InlineData(100000000000, 12)] + [InlineData(1000000000000, 13)] + [InlineData(10000000000000, 14)] + [InlineData(100000000000000, 15)] + [InlineData(1000000000000000, 16)] + [InlineData(10000000000000000, 17)] + [InlineData(100000000000000000, 18)] + [InlineData(1000000000000000000, 19)] + [InlineData(-1, 1)] + [InlineData(-10, 2)] + [InlineData(-100, 3)] + [InlineData(-1000, 4)] + [InlineData(-10000, 5)] + [InlineData(-100000, 6)] + [InlineData(-1000000, 7)] + [InlineData(-10000000, 8)] + [InlineData(-100000000, 9)] + [InlineData(-1000000000, 10)] + [InlineData(-10000000000, 11)] + [InlineData(-100000000000, 12)] + [InlineData(-1000000000000, 13)] + [InlineData(-10000000000000, 14)] + [InlineData(-100000000000000, 15)] + [InlineData(-1000000000000000, 16)] + [InlineData(-10000000000000000, 17)] + [InlineData(-100000000000000000, 18)] + [InlineData(-1000000000000000000, 19)] + [InlineData(long.MinValue, 19)] + [InlineData(long.MaxValue, 19)] + public void GenericMathIntegerLengthShouldProduceExpectedResultInt64(long value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (UInt64)")] + [InlineData(0, 1)] + [InlineData(1, 1)] + [InlineData(10, 2)] + [InlineData(100, 3)] + [InlineData(1000, 4)] + [InlineData(10000, 5)] + [InlineData(100000, 6)] + [InlineData(1000000, 7)] + [InlineData(10000000, 8)] + [InlineData(100000000, 9)] + [InlineData(1000000000, 10)] + [InlineData(10000000000, 11)] + [InlineData(100000000000, 12)] + [InlineData(1000000000000, 13)] + [InlineData(10000000000000, 14)] + [InlineData(100000000000000, 15)] + [InlineData(1000000000000000, 16)] + [InlineData(10000000000000000, 17)] + [InlineData(100000000000000000, 18)] + [InlineData(1000000000000000000, 19)] + [InlineData(10000000000000000000, 20)] + [InlineData(ulong.MinValue, 1)] + [InlineData(ulong.MaxValue, 20)] + public void GenericMathIntegerLengthShouldProduceExpectedResultUInt64(ulong value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "GenericMath.IntegerLength should produce the expected result (Double)")] + [InlineData(0, 1)] + [InlineData(1.1, 1)] + [InlineData(10.1, 2)] + [InlineData(100.1, 3)] + [InlineData(1000.1, 4)] + [InlineData(10000.1, 5)] + [InlineData(100000.1, 6)] + [InlineData(1000000.1, 7)] + [InlineData(10000000.1, 8)] + [InlineData(100000000.1, 9)] + [InlineData(1000000000.1, 10)] + [InlineData(10000000000.1, 11)] + [InlineData(100000000000.1, 12)] + [InlineData(1000000000000.1, 13)] + [InlineData(10000000000000.1, 14)] + [InlineData(100000000000000.1, 15)] + [InlineData(1000000000000000.1, 16)] + [InlineData(10000000000000000.1, 17)] + [InlineData(100000000000000000.1, 18)] + [InlineData(1000000000000000000.1, 19)] + [InlineData(10000000000000000000.1, 20)] + [InlineData(double.MinValue, 309)] + [InlineData(double.MaxValue, 309)] + public void GenericMathIntegerLengthShouldProduceExpectedResultDouble(double value, int expected) + { + // When + int actual = GenericMath.IntegerLength(value); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/GenericMathMinMaxTests.cs b/OnixLabs.Numerics.UnitTests/GenericMathMinMaxTests.cs new file mode 100644 index 0000000..0fb0976 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/GenericMathMinMaxTests.cs @@ -0,0 +1,44 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class GenericMathMinMaxTests +{ + [Theory(DisplayName = "GenericMath.MinMax should produce the expected result")] + [InlineData(0, 0, 0, 0)] + [InlineData(0, 1, 0, 1)] + [InlineData(1, 0, 0, 1)] + [InlineData(-1, 0, -1, 0)] + [InlineData(0, -1, -1, 0)] + [InlineData(123, 456, 123, 456)] + [InlineData(456, 123, 123, 456)] + [InlineData(123.456, 456.789, 123.456, 456.789)] + [InlineData(456.789, 123.456, 123.456, 456.789)] + [InlineData(-123, 456, -123, 456)] + [InlineData(-456, 123, -456, 123)] + [InlineData(-123.456, 456.789, -123.456, 456.789)] + [InlineData(-456.789, 123.456, -456.789, 123.456)] + public void GenericMathMinMaxShouldProduceExpectedResult(double left, double right, double expectedMin, double expectedMax) + { + // When + (double actualMin, double actualMax) = GenericMath.MinMax(left, right); + + // Then + Assert.Equal(expectedMin, actualMin); + Assert.Equal(expectedMax, actualMax); + } +} diff --git a/OnixLabs.Numerics.UnitTests/NumberInfoConstantTests.cs b/OnixLabs.Numerics.UnitTests/NumberInfoConstantTests.cs new file mode 100644 index 0000000..2bfd308 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/NumberInfoConstantTests.cs @@ -0,0 +1,90 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class NumberInfoConstantTests +{ + [Fact(DisplayName = "NumberInfo.Zero should produce the expected result")] + public void NumberInfoZeroShouldProduceExpectedResult() + { + // Given + const int exponent = 0; + const int precision = 1; + const int sign = 0; + const int scale = 0; + BigInteger significand = 0; + BigInteger unscaledValue = 0; + + // When + NumberInfo candidate = NumberInfo.Zero; + + // Then + Assert.Equal(significand, candidate.Significand); + Assert.Equal(exponent, candidate.Exponent); + Assert.Equal(precision, candidate.Precision); + Assert.Equal(sign, candidate.Sign); + Assert.Equal(unscaledValue, candidate.UnscaledValue); + Assert.Equal(scale, candidate.Scale); + } + + [Fact(DisplayName = "NumberInfo.One should produce the expected result")] + public void NumberInfoOneShouldProduceExpectedResult() + { + // Given + const int exponent = 0; + const int precision = 1; + const int sign = 1; + const int scale = 0; + BigInteger significand = 1; + BigInteger unscaledValue = 1; + + // When + NumberInfo candidate = NumberInfo.One; + + // Then + Assert.Equal(significand, candidate.Significand); + Assert.Equal(exponent, candidate.Exponent); + Assert.Equal(precision, candidate.Precision); + Assert.Equal(sign, candidate.Sign); + Assert.Equal(unscaledValue, candidate.UnscaledValue); + Assert.Equal(scale, candidate.Scale); + } + + [Fact(DisplayName = "NumberInfo.NegativeOne should produce the expected result")] + public void NumberInfoNegativeOneShouldProduceExpectedResult() + { + // Given + const int exponent = 0; + const int precision = 1; + const int sign = -1; + const int scale = 0; + BigInteger significand = -1; + BigInteger unscaledValue = -1; + + // When + NumberInfo candidate = NumberInfo.NegativeOne; + + // Then + Assert.Equal(significand, candidate.Significand); + Assert.Equal(exponent, candidate.Exponent); + Assert.Equal(precision, candidate.Precision); + Assert.Equal(sign, candidate.Sign); + Assert.Equal(unscaledValue, candidate.UnscaledValue); + Assert.Equal(scale, candidate.Scale); + } +} diff --git a/OnixLabs.Numerics.UnitTests/NumberInfoEqualityComparerTests.cs b/OnixLabs.Numerics.UnitTests/NumberInfoEqualityComparerTests.cs new file mode 100644 index 0000000..f0613e5 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/NumberInfoEqualityComparerTests.cs @@ -0,0 +1,57 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class NumberInfoEqualityComparerTests +{ + [NumberInfoEqualityComparerData] + [Theory(DisplayName = "NumberInfoEqualityComparer.Equals should produce the expected result (Strict)")] + public void NumberInfoEqualityComparerEqualsShouldProduceExpectedResultStrict(decimal left, decimal right, Guid _) + { + // Given + bool expected = left == right && left.Scale == right.Scale; + NumberInfo leftCandidate = left.ToNumberInfo(); + NumberInfo rightCandidate = right.ToNumberInfo(); + + // When + bool actualFromComparer = NumberInfoEqualityComparer.Strict.Equals(leftCandidate, rightCandidate); + bool actualFromNumberInfo = leftCandidate.Equals(rightCandidate); + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromNumberInfo); + } + + [NumberInfoEqualityComparerData] + [Theory(DisplayName = "NumberInfoEqualityComparer.Equals should produce the expected result (Semantic)")] + public void NumberInfoEqualityComparerEqualsShouldProduceExpectedResultSemantic(decimal left, decimal right, Guid _) + { + // Given + bool expected = left == right; + NumberInfo leftCandidate = left.ToNumberInfo(); + NumberInfo rightCandidate = right.ToNumberInfo(); + + // When + bool actualFromComparer = NumberInfoEqualityComparer.Semantic.Equals(leftCandidate, rightCandidate); + bool actualFromNumberInfo = leftCandidate == rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromNumberInfo); + } +} diff --git a/OnixLabs.Numerics.UnitTests/NumberInfoOrdinalityComparerTests.cs b/OnixLabs.Numerics.UnitTests/NumberInfoOrdinalityComparerTests.cs new file mode 100644 index 0000000..2138fcd --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/NumberInfoOrdinalityComparerTests.cs @@ -0,0 +1,129 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class NumberInfoOrdinalityComparerTests +{ + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "NumberInfoOrdinalityComparer.Compare should produce the expected result")] + public void NumberInfoOrdinalityComparerCompareShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + int expected = left.CompareTo(right); + NumberInfo leftCandidate = left.ToNumberInfo(); + NumberInfo rightCandidate = right.ToNumberInfo(); + + // When + int actualFromComparer = NumberInfoOrdinalityComparer.Default.Compare(leftCandidate, rightCandidate); + int actualFromNumberInfo = leftCandidate.CompareTo(rightCandidate); + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromNumberInfo); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "NumberInfoOrdinalityComparer.IsEqual should produce the expected result")] + public void NumberInfoOrdinalityComparerIsEqualShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left.CompareTo(right) is 0; + NumberInfo leftCandidate = left.ToNumberInfo(); + NumberInfo rightCandidate = right.ToNumberInfo(); + + // When + bool actualFromComparer = NumberInfoOrdinalityComparer.Default.IsEqual(leftCandidate, rightCandidate); + bool actualFromNumberInfo = leftCandidate.CompareTo(rightCandidate) is 0; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromNumberInfo); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "NumberInfoOrdinalityComparer.IsGreaterThan should produce the expected result")] + public void NumberInfoOrdinalityComparerIsGreaterThanShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left > right; + NumberInfo leftCandidate = left.ToNumberInfo(); + NumberInfo rightCandidate = right.ToNumberInfo(); + + // When + bool actualFromComparer = NumberInfoOrdinalityComparer.Default.IsGreaterThan(leftCandidate, rightCandidate); + bool actualFromNumberInfo = leftCandidate > rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromNumberInfo); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "NumberInfoOrdinalityComparer.IsGreaterThanOrEqual should produce the expected result")] + public void NumberInfoOrdinalityComparerIsGreaterOrEqualThanShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left >= right; + NumberInfo leftCandidate = left.ToNumberInfo(); + NumberInfo rightCandidate = right.ToNumberInfo(); + + // When + bool actualFromComparer = NumberInfoOrdinalityComparer.Default.IsGreaterThanOrEqual(leftCandidate, rightCandidate); + bool actualFromNumberInfo = leftCandidate >= rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromNumberInfo); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "NumberInfoOrdinalityComparer.IsLessThan should produce the expected result")] + public void NumberInfoOrdinalityComparerIsLessThanShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left < right; + NumberInfo leftCandidate = left.ToNumberInfo(); + NumberInfo rightCandidate = right.ToNumberInfo(); + + // When + bool actualFromComparer = NumberInfoOrdinalityComparer.Default.IsLessThan(leftCandidate, rightCandidate); + bool actualFromNumberInfo = leftCandidate < rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromNumberInfo); + } + + [NumberInfoOrdinalityComparerData] + [Theory(DisplayName = "NumberInfoOrdinalityComparer.IsLessThanOrEqual should produce the expected result")] + public void NumberInfoOrdinalityComparerIsLessOrEqualThanShouldProduceExpectedResult(decimal left, decimal right, Guid _) + { + // Given + bool expected = left <= right; + NumberInfo leftCandidate = left.ToNumberInfo(); + NumberInfo rightCandidate = right.ToNumberInfo(); + + // When + bool actualFromComparer = NumberInfoOrdinalityComparer.Default.IsLessThanOrEqual(leftCandidate, rightCandidate); + bool actualFromNumberInfo = leftCandidate <= rightCandidate; + + // Then + Assert.Equal(expected, actualFromComparer); + Assert.Equal(expected, actualFromNumberInfo); + } +} diff --git a/OnixLabs.Numerics.UnitTests/NumberInfoParseTests.cs b/OnixLabs.Numerics.UnitTests/NumberInfoParseTests.cs new file mode 100644 index 0000000..3861b3c --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/NumberInfoParseTests.cs @@ -0,0 +1,112 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class NumberInfoParseTests +{ + [NumberFormatData] + [Theory(DisplayName = "NumberInfo.Parse should produce the expected result (Currency)")] + public void NumberInfoParseShouldProduceExpectedResultCurrency(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToString("C", culture); + NumberInfo expected = decimal.Parse(formatted, NumberStyles.Currency, culture).ToNumberInfo(); + + // When + NumberInfo actual = NumberInfo.Parse(formatted, NumberStyles.Currency, culture); + + // Then + Assert.Equal(expected, actual, NumberInfoEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "NumberInfo.Parse should produce the expected result (Decimal, Integer)")] + public void NumberInfoParseShouldProduceExpectedResultDecimalInteger(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = Int128.CreateTruncating(value).ToString("D", culture); + NumberInfo expected = Int128.Parse(formatted, NumberStyles.Integer, culture).ToNumberInfo(); + + // When + NumberInfo actual = NumberInfo.Parse(formatted, NumberStyles.Integer, culture); + + // Then + Assert.Equal(expected, actual, NumberInfoEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "NumberInfo.Parse should produce the expected result (Decimal, BigDecimal)")] + public void NumberInfoParseShouldProduceExpectedResultDecimalBigDecimal(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToBigDecimal().ToString("D", culture); + NumberInfo expected = value.ToNumberInfo(); + + // When + NumberInfo actual = NumberInfo.Parse(formatted, NumberStyles.Number, culture); + + // Then + Assert.Equal(expected, actual, NumberInfoEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "NumberInfo.Parse should produce the expected result (Fixed)")] + public void NumberInfoParseShouldProduceExpectedResultFixed(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToString("F", culture); + NumberInfo expected = decimal.Parse(formatted, NumberStyles.Float, culture).ToNumberInfo(); + + // When + NumberInfo actual = NumberInfo.Parse(formatted, NumberStyles.Float, culture); + + // Then + Assert.Equal(expected, actual, NumberInfoEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "NumberInfo.Parse should produce the expected result (General)")] + public void NumberInfoParseShouldProduceExpectedResultGeneral(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToString("G", culture); + NumberInfo expected = decimal.Parse(formatted, NumberStyles.Any, culture).ToNumberInfo(); + + // When + NumberInfo actual = NumberInfo.Parse(formatted, NumberStyles.Any, culture); + + // Then + Assert.Equal(expected, actual, NumberInfoEqualityComparer.Semantic); + } + + [NumberFormatData] + [Theory(DisplayName = "NumberInfo.Parse should produce the expected result (Number)")] + public void NumberInfoParseShouldProduceExpectedResultNumber(decimal value, CultureInfo culture, Guid _) + { + // Given + string formatted = value.ToString("N", culture); + NumberInfo expected = decimal.Parse(formatted, NumberStyles.Number, culture).ToNumberInfo(); + + // When + NumberInfo actual = NumberInfo.Parse(formatted, NumberStyles.Number, culture); + + // Then + Assert.Equal(expected, actual, NumberInfoEqualityComparer.Semantic); + } +} diff --git a/OnixLabs.Numerics.UnitTests/NumberInfoToStringTests.cs b/OnixLabs.Numerics.UnitTests/NumberInfoToStringTests.cs new file mode 100644 index 0000000..10814e0 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/NumberInfoToStringTests.cs @@ -0,0 +1,37 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class NumberInfoToStringTests +{ + [NumberFormatData] + [Theory(DisplayName = "NumberInfo.ToString should produce the expected result (General)")] + public void NumberInfoToStringShouldProduceExpectedResultGeneral(decimal value, CultureInfo culture, Guid _) + { + // Given + string expected = value.ToString("G", culture); + NumberInfo candidate = value.ToNumberInfo(); + + // When + string actual = candidate.ToString("G", culture); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Numerics.UnitTests/NumericsExtensionsTests.cs b/OnixLabs.Numerics.UnitTests/NumericsExtensionsTests.cs new file mode 100644 index 0000000..0bf7256 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/NumericsExtensionsTests.cs @@ -0,0 +1,230 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using System.Numerics; +using OnixLabs.Numerics.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Numerics.UnitTests; + +public sealed class NumericExtensionsTests +{ + [Theory(DisplayName = "Decimal.GetUnscaledValue should produce the expected result (decimal values)")] + [InlineData(0, 0)] + [InlineData(1, 1)] + [InlineData(-1, -1)] + [InlineData(0.000000001, 1)] + [InlineData(-0.000000001, -1)] + [InlineData(123456789, 123456789)] + [InlineData(12345678.9, 123456789)] + [InlineData(1234567.89, 123456789)] + [InlineData(123456.789, 123456789)] + [InlineData(12345.6789, 123456789)] + [InlineData(1234.56789, 123456789)] + [InlineData(123.456789, 123456789)] + [InlineData(12.3456789, 123456789)] + [InlineData(1.23456789, 123456789)] + [InlineData(-123456789, -123456789)] + [InlineData(-12345678.9, -123456789)] + [InlineData(-1234567.89, -123456789)] + [InlineData(-123456.789, -123456789)] + [InlineData(-12345.6789, -123456789)] + [InlineData(-1234.56789, -123456789)] + [InlineData(-123.456789, -123456789)] + [InlineData(-12.3456789, -123456789)] + [InlineData(-1.23456789, -123456789)] + [InlineData(1.000000001, 1000000001)] + public void DecimalGetUnscaledValueShouldProduceExpectedResultDecimal(decimal value, BigInteger expected) + { + // When + BigInteger actual = value.GetUnscaledValue(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Decimal.GetUnscaledValue should produce the expected result (value and scale)")] + [InlineData(123, 0, 123)] + [InlineData(123, 1, 1230)] + [InlineData(123, 2, 12300)] + [InlineData(123, 3, 123000)] + [InlineData(123, 4, 1230000)] + [InlineData(123, 5, 12300000)] + [InlineData(123, 6, 123000000)] + [InlineData(123, 7, 1230000000)] + [InlineData(123, 8, 12300000000)] + [InlineData(123, 9, 123000000000)] + [InlineData(123, 10, 1230000000000)] + public void DecimalGetUnscaledValueShouldProduceExpectedResultValueAndScale(int value, int scale, BigInteger expected) + { + // Given + decimal candidate = value.ToDecimal(scale, ScaleMode.Integral); + + // When + BigInteger actual = candidate.GetUnscaledValue(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "INumber.IsBetween should produce the expected result")] + [InlineData(0, 0, 0, true)] + [InlineData(0, 0, 1, true)] + [InlineData(0, -1, 1, true)] + [InlineData(0, 1, 2, false)] + public void NumberIsBetweenShouldProduceExpectedResult(int value, int minimum, int maximum, bool expected) + { + // When + bool actual = value.IsBetween(minimum, maximum); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "BinaryInteger.ToBigInteger should produce the expected result")] + [InlineData(0, 0)] + [InlineData(1, 1)] + [InlineData(-1, -1)] + [InlineData(123456789, 123456789)] + [InlineData(-123456789, -123456789)] + public void BinaryIntegerToBigIntegerShouldProduceExpectedResult(int value, BigInteger expected) + { + // When + BigInteger actual = value.ToBigInteger(); + + // Then + Assert.Equal(expected, actual); + } + + [NumericsExtensionsToDecimalData] + [Theory(DisplayName = "IBinaryInteger.ToDecimal should produce the expected result")] + public void BinaryIntegerToDecimalShouldProduceExpectedResult(Int128 value, int scale, ScaleMode mode, string expected) + { + // When + decimal candidate = value.ToDecimal(scale, mode); + string actual = candidate.ToString(CultureInfo.InvariantCulture); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "IBinaryInteger.ToDecimal should throw InvalidOperationException if a value is too large.")] + public void BinaryIntegerToDecimalShouldThrowInvalidOperationExceptionIfAValueIsTooLarge() + { + // When + InvalidOperationException exception = Assert.Throws(() => Int128.MaxValue.ToDecimal()); + + // Then + Assert.Equal($"Value is either too large or too small to convert to {nameof(Decimal)}.", exception.Message); + } + + [Fact(DisplayName = "IBinaryInteger.ToDecimal should throw InvalidOperationException if a value is too small.")] + public void BinaryIntegerToDecimalShouldThrowInvalidOperationExceptionIfAValueIsTooSmall() + { + // When + InvalidOperationException exception = Assert.Throws(() => Int128.MinValue.ToDecimal()); + + // Then + Assert.Equal($"Value is either too large or too small to convert to {nameof(Decimal)}.", exception.Message); + } + + [Fact(DisplayName = "IBinaryInteger.ToDecimal should throw ArgumentException if scale is less than zero.")] + public void BinaryIntegerToDecimalShouldThrowArgumentExceptionIfScaleIsLessThanZero() + { + // When + ArgumentException exception = Assert.Throws(() => 0.ToDecimal(-1)); + + // Then + Assert.Equal("Scale must be between 0 and 28.", exception.Message); + } + + [Fact(DisplayName = "IBinaryInteger.ToDecimal should throw ArgumentException if mode is not defined.")] + public void BinaryIntegerToDecimalShouldThrowArgumentExceptionIfModeIsNotDefined() + { + // When + ArgumentOutOfRangeException exception = Assert.Throws(() => 0.ToDecimal(0, (ScaleMode)2)); + + // Then + Assert.Equal("Invalid ScaleMode enum value: 2. Valid values include: Fractional, Integral. (Parameter 'mode')", exception.Message); + } + + [NumericsExtensionsToNumberInfoIntegerData] + [Theory(DisplayName = "IBinaryInteger.ToNumberInfo should produce the expected result")] + public void BinaryIntegerToNumberInfoProduceExpectedResultIntegerValues + (Int128 value, BigInteger unscaledValue, int scale, BigInteger significand, int exponent, int sign, int precision) + { + // When + NumberInfo candidate = value.ToNumberInfo(); + + // Then + Assert.Equal(significand, candidate.Significand); + Assert.Equal(exponent, candidate.Exponent); + Assert.Equal(precision, candidate.Precision); + Assert.Equal(sign, candidate.Sign); + Assert.Equal(unscaledValue, candidate.UnscaledValue); + Assert.Equal(scale, candidate.Scale); + } + + [NumericsExtensionsToNumberInfoFloatData] + [Theory(DisplayName = "Single.ToNumberInfo should produce the expected result")] + public void SingleToNumberInfoShouldProduceExpectedResultFloatValues + (float value, BigInteger unscaledValue, int scale, BigInteger significand, int exponent, int sign, int precision) + { + // When + NumberInfo candidate = value.ToNumberInfo(); + + // Then + Assert.Equal(significand, candidate.Significand); + Assert.Equal(exponent, candidate.Exponent); + Assert.Equal(precision, candidate.Precision); + Assert.Equal(sign, candidate.Sign); + Assert.Equal(unscaledValue, candidate.UnscaledValue); + Assert.Equal(scale, candidate.Scale); + } + + [NumericsExtensionsToNumberInfoDoubleData] + [Theory(DisplayName = "Double.ToNumberInfo should produce the expected result")] + public void NumberInfoCreateShouldProduceExpectedResultDoubleValues + (double value, BigInteger unscaledValue, int scale, BigInteger significand, int exponent, int sign, int precision) + { + // When + NumberInfo candidate = value.ToNumberInfo(); + + // Then + Assert.Equal(significand, candidate.Significand); + Assert.Equal(exponent, candidate.Exponent); + Assert.Equal(precision, candidate.Precision); + Assert.Equal(sign, candidate.Sign); + Assert.Equal(unscaledValue, candidate.UnscaledValue); + Assert.Equal(scale, candidate.Scale); + } + + [NumericsExtensionsToNumberInfoDecimalData] + [Theory(DisplayName = "Decimal.ToNumberInfo should produce the expected result")] + public void NumberInfoCreateShouldProduceExpectedResultDecimalValues + (decimal value, BigInteger unscaledValue, int scale, BigInteger significand, int exponent, int sign, int precision) + { + // When + NumberInfo candidate = value.ToNumberInfo(); + + // Then + Assert.Equal(significand, candidate.Significand); + Assert.Equal(exponent, candidate.Exponent); + Assert.Equal(precision, candidate.Precision); + Assert.Equal(sign, candidate.Sign); + Assert.Equal(unscaledValue, candidate.UnscaledValue); + Assert.Equal(scale, candidate.Scale); + } +} diff --git a/OnixLabs.Numerics.UnitTests/OnixLabs.Numerics.UnitTests.csproj b/OnixLabs.Numerics.UnitTests/OnixLabs.Numerics.UnitTests.csproj new file mode 100644 index 0000000..68667c4 --- /dev/null +++ b/OnixLabs.Numerics.UnitTests/OnixLabs.Numerics.UnitTests.csproj @@ -0,0 +1,30 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Abs.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Abs.cs new file mode 100644 index 0000000..a591696 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Abs.cs @@ -0,0 +1,30 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Gets the absolute value of the specified value. + /// + /// The from which to obtain an absolute value. + /// Returns the absolute value of the specified value. + public static BigDecimal Abs(BigDecimal value) + { + return new BigDecimal(BigInteger.Abs(value.UnscaledValue), value.Scale); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Addition.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Addition.cs new file mode 100644 index 0000000..57c1159 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Addition.cs @@ -0,0 +1,50 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Computes the sum of the specified values. + /// + /// The left-hand value to add to. + /// The right-hand value to add. + /// Returns the sum of the specified values. + public static BigDecimal Add(BigDecimal left, BigDecimal right) + { + int scale = MaxScale(left, right); + + if (IsZero(left)) return right.SetScale(scale); + if (IsZero(right)) return left.SetScale(scale); + + (BigInteger leftAddend, BigInteger rightAddend) = NormalizeUnscaledValues(left, right); + BigInteger sum = leftAddend + rightAddend; + + return new BigDecimal(sum, scale); + } + + /// + /// Computes the sum of the specified values. + /// + /// The left-hand value to add to. + /// The right-hand value to add. + /// Returns the sum of the specified values. + public static BigDecimal operator +(BigDecimal left, BigDecimal right) + { + return Add(left, right); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Decrement.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Decrement.cs new file mode 100644 index 0000000..c0d9592 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Decrement.cs @@ -0,0 +1,50 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Decrements the integral component of the specified value by one. + /// + /// The value to decrement. + /// Returns a new value decremented by one integral unit. + public static BigDecimal Decrement(BigDecimal value) + { + return new BigDecimal(value.UnscaledValue - value.number.ScaleFactor, value.Scale); + } + + /// + /// Decrements the fractional component of the specified value by one. + /// + /// The value to decrement. + /// Returns a new value decremented by one fractional unit. + public static BigDecimal DecrementFraction(BigDecimal value) + { + return new BigDecimal(value.UnscaledValue - BigInteger.One, value.Scale); + } + + /// + /// Decrements the integral component of the specified value by one. + /// + /// The value to decrement. + /// Returns a new value decremented by one integral unit. + public static BigDecimal operator --(BigDecimal value) + { + return Decrement(value); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Division.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Division.cs new file mode 100644 index 0000000..7601563 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Division.cs @@ -0,0 +1,80 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Computes the quotient of the specified values. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// The rounding strategy to use. The default value is . + /// Returns the quotient of the specified values. + public static BigDecimal Divide(BigDecimal left, BigDecimal right, MidpointRounding mode = default) + { + RequireIsDefined(mode, nameof(mode)); + + if (right == Zero) throw new DivideByZeroException(); + if (right == One) return left; + if (left == Zero) return Zero; + + BigInteger dividend = left.UnscaledValue * BigInteger.Pow(10, right.Scale); + BigInteger quotient = DivideAndRound(dividend, right.UnscaledValue, mode); + + return new BigDecimal(quotient, left.Scale); + } + + /// + /// Computes the quotient of the specified values. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// Returns the quotient of the specified values. + public static BigDecimal operator /(BigDecimal left, BigDecimal right) + { + return Divide(left, right); + } + + /// + /// Divides the specified dividend by the specified divisor and rounds the remainder using the specified rounding mode. + /// + /// The dividend value to divide. + /// The divisor to divide by. + /// The rounding strategy to use. The default value is . + /// Returns the quotient of the specified values, rounded using the specified rounding mode. + private static BigInteger DivideAndRound(BigInteger dividend, BigInteger divisor, MidpointRounding mode) + { + // 1. Obtain the quotient and remainder by dividing the dividend by the divisor. + (BigInteger quotient, BigInteger remainder) = BigInteger.DivRem(dividend, divisor); + + // 2. Obtain the unit value of the quotient as this is required to accurately round towards an even number. + int unit = (int)(quotient % 10); + + // 3. Obtain the remainder with 10 digits of precision, which is required for accurate rounding. + remainder = remainder * RoundingMagnitude / divisor; + + // 4. Convert the remainder to a double with 10 digits of fractional precision and add the unit. + double valueToRound = (double)remainder / RoundingMagnitude + unit; + + // 5. Round until zero fractional digits remain and subtract the unit; yields 1 or 0. + int rounded = (int)Math.Round(valueToRound, mode) - unit; + + return quotient + rounded; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Increment.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Increment.cs new file mode 100644 index 0000000..e07be52 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Increment.cs @@ -0,0 +1,53 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Increments the integral component of the specified value by one. + /// + /// The value to increment. + /// Returns a new value incremented by one integral unit. + public static BigDecimal Increment(BigDecimal value) + { + BigInteger power = BigInteger.Pow(10, value.Scale); + (BigInteger quotient, BigInteger remainder) = BigInteger.DivRem(value.UnscaledValue, power); + + return new BigDecimal((quotient + 1) * power + remainder, value.Scale); + } + + /// + /// Increments the fractional component of the specified value by one. + /// + /// The value to increment. + /// Returns a new value incremented by one fractional unit. + public static BigDecimal IncrementFraction(BigDecimal value) + { + return new BigDecimal(value.UnscaledValue + 1, value.Scale); + } + + /// + /// Increments the integral component of the specified value by one. + /// + /// The value to increment. + /// Returns a new value incremented by one integral unit. + public static BigDecimal operator ++(BigDecimal value) + { + return Increment(value); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Modulus.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Modulus.cs new file mode 100644 index 0000000..35d0d0b --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Modulus.cs @@ -0,0 +1,47 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Gets the modulus of the specified values by dividing the left-hand value by the right-hand value. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// Returns the modulus of the specified values by dividing the left-hand value by the right-hand value. + public static BigDecimal Mod(BigDecimal left, BigDecimal right) + { + int scale = MaxScale(left, right); + + (BigInteger dividend, BigInteger divisor) = NormalizeUnscaledValues(left, right); + BigInteger remainder = BigInteger.Remainder(dividend, divisor); + + return new BigDecimal(remainder, scale); + } + + /// + /// Gets the modulus of the specified values by dividing the left-hand value by the right-hand value. + /// + /// The left-hand value to divide. + /// The right-hand value to divide by. + /// Returns the modulus of the specified values by dividing the left-hand value by the right-hand value. + public static BigDecimal operator %(BigDecimal left, BigDecimal right) + { + return Mod(left, right); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Multiplication.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Multiplication.cs new file mode 100644 index 0000000..4055dae --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Multiplication.cs @@ -0,0 +1,47 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Computes the product of the specified values. + /// + /// The left-hand value to multiply by. + /// The right-hand value to multiply. + /// Returns the product of the specified values. + public static BigDecimal Multiply(BigDecimal left, BigDecimal right) + { + int scale = left.Scale + right.Scale; + + if (IsZero(left) || IsZero(right)) return new BigDecimal(0, scale); + BigInteger product = left.UnscaledValue * right.UnscaledValue; + + return new BigDecimal(product, scale); + } + + /// + /// Computes the product of the specified values. + /// + /// The left-hand value to multiply by. + /// The right-hand value to multiply. + /// Returns the product of the specified values. + public static BigDecimal operator *(BigDecimal left, BigDecimal right) + { + return Multiply(left, right); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Pow.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Pow.cs new file mode 100644 index 0000000..c9addb3 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Pow.cs @@ -0,0 +1,45 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Computes the power of the specified value, raised to the power of the specified exponent. + /// + /// The value to raise. + /// The exponent to raise by. + /// Specifies the rounding mode that should be applied for values raised to the power of a negative exponent. + /// Returns the power of the specified value, raised to the power of the specified exponent. + public static BigDecimal Pow(BigDecimal value, int exponent, MidpointRounding mode = default) + { + if (IsZero(value)) + { + if (exponent < 0) throw new DivideByZeroException(); + return exponent is 0 ? One : Zero; + } + + if (exponent is 0) return One; + if (exponent is 1) return value; + + BigDecimal result = Abs(value); + int absExponent = int.Abs(exponent); + while (--absExponent > 0) result *= Abs(value); + + return (exponent < 0 ? Divide(One.SetScale(value.Scale), result, mode) : result) * value.number.Sign; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Round.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Round.cs new file mode 100644 index 0000000..99de06b --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Round.cs @@ -0,0 +1,98 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Rounds the specified value. + /// + /// The value to round. + /// The number of decimal places to round by. The default value is zero. + /// The rounding mode to round by. The default value is . + /// Returns a value rounded to the specified number of fractional digits. + /// If the specified scale is non-negative. + /// If the specified rounding mode is invalid. + public static BigDecimal Round(BigDecimal value, int scale = default, MidpointRounding mode = default) + { + Require(scale >= 0, "Scale must be greater than or equal to zero.", nameof(scale)); + RequireIsDefined(mode, nameof(mode)); + + if (scale >= value.Scale) return value; + + BigInteger divisor = BigInteger.Pow(10, value.Scale - scale); + BigInteger quotient = DivideAndRound(value.UnscaledValue, divisor, mode); + + return new BigDecimal(quotient, scale); + } + + /// + /// Rounds the specified value up to the smallest integral value greater than or equal to the specified number. + /// This kind of rounding is sometimes called rounding towards positive infinity, following IEEE Standard 754, section 4. + /// + /// The value to be rounded up towards positive infinity. + /// Returns the smallest integral value that is greater than or equal to the specified value. + public static BigDecimal Ceiling(BigDecimal value) + { + return Round(value, 0, MidpointRounding.ToPositiveInfinity); + } + + /// + /// Rounds the specified value down to the largest integral value less than or equal to the specified number. + /// This kind of rounding is sometimes called rounding towards negative infinity, following IEEE Standard 754, section 4. + /// + /// The value to be rounded down towards positive infinity. + /// Returns the largest integral value that is less than or equal to the specified value. + public static BigDecimal Floor(BigDecimal value) + { + return Round(value, 0, MidpointRounding.ToNegativeInfinity); + } + + /// + /// Rounds the current value. + /// + /// The number of decimal places to round by. The default value is zero. + /// The rounding mode to round by. The default value is . + /// Returns a value rounded to the specified number of fractional digits. + /// If the specified scale is non-negative. + /// If the specified rounding mode is invalid. + public BigDecimal Round(int scale = default, MidpointRounding mode = default) + { + return Round(this, scale, mode); + } + + /// + /// Rounds the current value up to the smallest integral value greater than or equal to the current number. + /// This kind of rounding is sometimes called rounding towards positive infinity, following IEEE Standard 754, section 4. + /// + /// Returns the smallest integral value that is greater than or equal to the current value. + public BigDecimal Ceiling() + { + return Ceiling(this); + } + + /// + /// Rounds the current value down to the largest integral value less than or equal to the current number. + /// This kind of rounding is sometimes called rounding towards negative infinity, following IEEE Standard 754, section 4. + /// + /// Returns the largest integral value that is less than or equal to the current value. + public BigDecimal Floor() + { + return Floor(this); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Scale.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Scale.cs new file mode 100644 index 0000000..890e447 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Scale.cs @@ -0,0 +1,66 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Sets the scale of the specified value. + /// + /// The value to scale. + /// The scale to apply to the value. + /// The mode to be used when the specified scale is less than the current scale. + /// Returns a new value with the specified scale. + public static BigDecimal SetScale(BigDecimal value, int scale, MidpointRounding mode = default) + { + Require(scale >= 0, "Scale must be greater than or equal to zero.", nameof(scale)); + RequireIsDefined(mode, nameof(mode)); + + if (scale == value.Scale) return value; + if (scale < value.Scale) return Round(value, scale, mode); + + BigInteger magnitude = BigInteger.Pow(10, scale - value.Scale); + return new BigDecimal(value.UnscaledValue * magnitude, scale); + } + + /// + /// Sets the scale of the specified value. + /// + /// The scale to apply to the value. + /// The mode to be used when the specified scale is less than the current scale. + /// Returns a new value with the specified scale. + public BigDecimal SetScale(int scale, MidpointRounding mode = default) + { + return SetScale(this, scale, mode); + } + + /// + /// Normalizes the unscaled values of the specified values. + /// + /// The left-hand value to normalize. + /// The right-hand value to normalize. + /// Returns the normalized unscaled values of the specified values. + public static (BigInteger Left, BigInteger Right) NormalizeUnscaledValues(BigDecimal left, BigDecimal right) + { + BigInteger minOrderOfMagnitude = BigInteger.Min(left.number.ScaleFactor, right.number.ScaleFactor); + BigInteger leftNormalized = left.UnscaledValue * right.number.ScaleFactor / minOrderOfMagnitude; + BigInteger rightNormalized = right.UnscaledValue * left.number.ScaleFactor / minOrderOfMagnitude; + + return (leftNormalized, rightNormalized); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Subtraction.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Subtraction.cs new file mode 100644 index 0000000..248ddab --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Subtraction.cs @@ -0,0 +1,50 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Computes the difference between the specified values. + /// + /// The left-hand value to subtract from. + /// The right-hand value to subtract. + /// Returns the difference between the specified values. + public static BigDecimal Subtract(BigDecimal left, BigDecimal right) + { + int scale = MaxScale(left, right); + + if (IsZero(left)) return -right.SetScale(scale); + if (IsZero(right)) return left.SetScale(scale); + + (BigInteger minuend, BigInteger subtrahend) = NormalizeUnscaledValues(left, right); + BigInteger difference = minuend - subtrahend; + + return new BigDecimal(difference, scale); + } + + /// + /// Computes the difference between the specified values. + /// + /// The left-hand value to subtract from. + /// The right-hand value to subtract. + /// Returns the difference between the specified values. + public static BigDecimal operator -(BigDecimal left, BigDecimal right) + { + return Subtract(left, right); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Trim.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Trim.cs new file mode 100644 index 0000000..dd8b681 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Trim.cs @@ -0,0 +1,43 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Trims any trailing zeros from the fractional part of the specified value. + /// + /// The value from which to trim trailing zeros. + /// Returns a new excluding any trailing zeros. + public static BigDecimal TrimTrailingZeros(BigDecimal value) + { + if (IsZero(value)) return Zero; + + int exponent = 0; + while (value.UnscaledValue % BigInteger.Pow(10, exponent) == 0) exponent++; + return new BigDecimal(value.UnscaledValue / BigInteger.Pow(10, --exponent), value.Scale - exponent); + } + + /// + /// Trims any trailing zeros from the fractional part of the current value. + /// + /// Returns a new excluding any trailing zeros. + public BigDecimal TrimTrailingZeros() + { + return TrimTrailingZeros(this); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.Truncate.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.Truncate.cs new file mode 100644 index 0000000..1b2bb23 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.Truncate.cs @@ -0,0 +1,27 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Truncates the fractional part of the specified value, leaving only the integral component. + /// + /// Returns the fractional part of the specified value, leaving only the integral component. + public static BigDecimal Truncate(BigDecimal value) + { + return value.number.Integer; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.UnaryAddition.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.UnaryAddition.cs new file mode 100644 index 0000000..aa96e0d --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.UnaryAddition.cs @@ -0,0 +1,38 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Computes the unary addition of the specified value. + /// + /// The value for which to perform unary addition. + /// Returns the unary addition of the specified value. + public static BigDecimal UnaryAdd(BigDecimal value) + { + return value; + } + + /// + /// Computes the unary addition of the specified value. + /// + /// The value for which to perform unary addition. + /// Returns the unary addition of the specified value. + public static BigDecimal operator +(BigDecimal value) + { + return UnaryAdd(value); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Arithmetic.UnarySubtraction.cs b/OnixLabs.Numerics/BigDecimal.Arithmetic.UnarySubtraction.cs new file mode 100644 index 0000000..6f31f2c --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Arithmetic.UnarySubtraction.cs @@ -0,0 +1,38 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Computes the unary subtraction of the specified value. + /// + /// The value for which to perform unary subtraction. + /// Returns the unary subtraction of the specified value. + public static BigDecimal UnarySubtract(BigDecimal value) + { + return new BigDecimal(-value.UnscaledValue, value.Scale); + } + + /// + /// Computes the unary subtraction of the specified value. + /// + /// The value for which to perform unary subtraction. + /// Returns the unary subtraction of the specified value. + public static BigDecimal operator -(BigDecimal value) + { + return UnarySubtract(value); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Comparable.MinMax.cs b/OnixLabs.Numerics/BigDecimal.Comparable.MinMax.cs new file mode 100644 index 0000000..7b8d874 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Comparable.MinMax.cs @@ -0,0 +1,158 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Gets the lesser of the specified values. + /// + /// The left value to compare. + /// The right value to compare. + /// Returns the lesser of the specified values. + public static BigDecimal Min(BigDecimal left, BigDecimal right) + { + return left < right ? left : right; + } + + /// + /// Gets the greater of the specified values. + /// + /// The left value to compare. + /// The right value to compare. + /// Returns the greater of the specified values. + public static BigDecimal Max(BigDecimal left, BigDecimal right) + { + return left > right ? left : right; + } + + /// + /// Gets the lesser and the greater of the specified values. + /// + /// The left value to compare. + /// The right value to compare. + /// Returns the lesser and the greater of the specified values. + public static (BigDecimal Min, BigDecimal Max) MinMax(BigDecimal left, BigDecimal right) + { + BigDecimal min = Min(left, right); + BigDecimal max = Max(left, right); + + return (min, max); + } + + /// + /// Gets the lesser of the specified values. + /// + /// The left value to compare. + /// The right value to compare. + /// Returns the lesser of the specified values. + public static BigDecimal MinMagnitude(BigDecimal x, BigDecimal y) + { + BigDecimal left = Abs(x); + BigDecimal right = Abs(y); + + return left < right || left == right && IsNegative(x) ? x : y; + } + + /// + /// Gets the greater of the specified values. + /// + /// The left value to compare. + /// The right value to compare. + /// Returns the greater of the specified values. + public static BigDecimal MaxMagnitude(BigDecimal x, BigDecimal y) + { + BigDecimal left = Abs(x); + BigDecimal right = Abs(y); + + return left > right || left == right && !IsNegative(x) ? x : y; + } + + /// + /// Gets the lesser and the greater of the specified values by magnitude. + /// + /// The left value to compare. + /// The right value to compare. + /// Returns the lesser and the greater of the specified values by magnitude. + public static (BigDecimal MinMagnitude, BigDecimal MaxMagnitude) MinMaxMagnitude(BigDecimal left, BigDecimal right) + { + BigDecimal minMagnitude = MinMagnitude(left, right); + BigDecimal maxMagnitude = MaxMagnitude(left, right); + + return (minMagnitude, maxMagnitude); + } + + /// + /// Obtains the minimum scale of the specified left-hand and right-hand values. + /// + /// The left-hand value from which to obtain the minimum scale value. + /// The left-hand value from which to obtain the minimum scale value. + /// Returns the minimum scale of the specified left-hand and right-hand values. + public static int MinScale(BigDecimal left, BigDecimal right) + { + return int.Min(left.Scale, right.Scale); + } + + /// + /// Obtains the maximum scale of the specified left-hand and right-hand values. + /// + /// The left-hand value from which to obtain the maximum scale value. + /// The left-hand value from which to obtain the maximum scale value. + /// Returns the maximum scale of the specified left-hand and right-hand values. + public static int MaxScale(BigDecimal left, BigDecimal right) + { + return int.Max(left.Scale, right.Scale); + } + + /// + /// Obtains the minimum and maximum scale of the specified left-hand and right-hand values. + /// + /// The left-hand value from which to obtain the minimum and maximum values. + /// The left-hand value from which to obtain the minimum and maximum values. + /// Returns the minimum and maximum of the specified left-hand and right-hand values. + public static (int Min, int Max) MinMaxScale(BigDecimal left, BigDecimal right) + { + int min = MinScale(left, right); + int max = MaxScale(left, right); + + return (min, max); + } + + + + /// + /// Gets the lesser of the specified values. + /// + /// The left value to compare. + /// The right value to compare. + /// Returns the lesser of the specified values. + static BigDecimal INumberBase.MinMagnitudeNumber(BigDecimal x, BigDecimal y) + { + return MinMagnitude(x, y); + } + + /// + /// Gets the greater of the specified values. + /// + /// The left value to compare. + /// The right value to compare. + /// Returns the greater of the specified values. + static BigDecimal INumberBase.MaxMagnitudeNumber(BigDecimal x, BigDecimal y) + { + return MaxMagnitude(x, y); + } +} diff --git a/OnixLabs.Core/Units/DataSize.Comparable.cs b/OnixLabs.Numerics/BigDecimal.Comparable.cs similarity index 63% rename from OnixLabs.Core/Units/DataSize.Comparable.cs rename to OnixLabs.Numerics/BigDecimal.Comparable.cs index 1a994e3..18f9349 100644 --- a/OnixLabs.Core/Units/DataSize.Comparable.cs +++ b/OnixLabs.Numerics/BigDecimal.Comparable.cs @@ -1,33 +1,31 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using System; +namespace OnixLabs.Numerics; -namespace OnixLabs.Core.Units; - -public readonly partial struct DataSize : IComparable>, IComparable +public readonly partial struct BigDecimal { /// - /// Compares two values and returns an integer that indicates - /// whether the left-hand value is less than, equal to, or greater than the right-hand value. + /// Compares two values and returns an integer that indicates + /// whether the left-hand value is less than, equal to, or greater than the right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. /// Returns a value that indicates the relative order of the objects being compared. - public static int Compare(DataSize left, DataSize right) + public static int Compare(BigDecimal left, BigDecimal right) { - return left.Bits.CompareTo(right.Bits); + return BigDecimalOrdinalityComparer.Default.Compare(left, right); } /// @@ -35,11 +33,11 @@ public static int Compare(DataSize left, DataSize right) /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the /// other object. /// - /// An object to compare with this instance. + /// An object to compare with this instance. /// Returns a value that indicates the relative order of the objects being compared. - public int CompareTo(DataSize other) + public int CompareTo(object? obj) { - return Compare(this, other); + return BigDecimalOrdinalityComparer.Default.Compare(this, obj); } /// @@ -47,54 +45,54 @@ public int CompareTo(DataSize other) /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the /// other object. /// - /// An object to compare with this instance. + /// An object to compare with this instance. /// Returns a value that indicates the relative order of the objects being compared. - public int CompareTo(object? obj) + public int CompareTo(BigDecimal other) { - return this.CompareObject(obj); + return Compare(this, other); } /// - /// Performs a greater than comparison check between two values. + /// Determines whether the left-hand value is greater than the right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is greater than right-hand operand; otherwise, false. - public static bool operator >(DataSize left, DataSize right) + /// Returns True if the left-hand operand is greater than right-hand operand; otherwise, false. + public static bool operator >(BigDecimal left, BigDecimal right) { - return Compare(left, right) is 1; + return BigDecimalOrdinalityComparer.Default.IsGreaterThan(left, right); } /// - /// Performs a greater than or equal comparison check between two values. + /// Determines whether the left-hand value is greater than or equal to the right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is greater than or equal to right-hand operand; otherwise, false. - public static bool operator >=(DataSize left, DataSize right) + /// Returns true if the left-hand operand is greater than or equal to the right-hand operand; otherwise, false. + public static bool operator >=(BigDecimal left, BigDecimal right) { - return Compare(left, right) is 1 or 0; + return BigDecimalOrdinalityComparer.Default.IsGreaterThanOrEqual(left, right); } /// - /// Performs a less than comparison check between two values. + /// Determines whether the left-hand value is less than right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is less than right-hand operand; otherwise, false. - public static bool operator <(DataSize left, DataSize right) + /// Returns true if the left-hand operand is less than the right-hand operand; otherwise, false. + public static bool operator <(BigDecimal left, BigDecimal right) { - return Compare(left, right) is -1; + return BigDecimalOrdinalityComparer.Default.IsLessThan(left, right); } /// - /// Performs a less than or equal comparison check between two values. + /// Determines whether the left-hand value is less than or equal to the right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is less than or equal to right-hand operand; otherwise, false. - public static bool operator <=(DataSize left, DataSize right) + /// Returns true if the left-hand operand is less than or equal to the right-hand operand; otherwise, false. + public static bool operator <=(BigDecimal left, BigDecimal right) { - return Compare(left, right) is -1 or 0; + return BigDecimalOrdinalityComparer.Default.IsLessThanOrEqual(left, right); } } diff --git a/OnixLabs.Numerics/BigDecimal.Constants.cs b/OnixLabs.Numerics/BigDecimal.Constants.cs new file mode 100644 index 0000000..9bc5240 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Constants.cs @@ -0,0 +1,93 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Gets a negative one -1 value. + /// + public static BigDecimal NegativeOne => -1; + + /// + /// Gets a zero 0 value. + /// + public static BigDecimal Zero => 0; + + /// + /// Gets a one 1 value. + /// + public static BigDecimal One => 1; + + /// + /// Gets a two 2 value. + /// + public static BigDecimal Two => 2; + + /// + /// Gets a ten 10 value. + /// + public static BigDecimal Ten => 10; + + /// Gets the natural logarithmic base, specified by the constant, e. + /// This value is accurate to a precision of 1001 decimal digits. + public static BigDecimal E => Parse("2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274274663919320030599218174135966290435729003342952605956307381323286279434907632338298807531952510190115738341879307021540891499348841675092447614606680822648001684774118537423454424371075390777449920695517027618386062613313845830007520449338265602976067371132007093287091274437470472306969772093101416928368190255151086574637721112523897844250569536967707854499699679468644549059879316368892300987931277361782154249992295763514822082698951936680331825288693984964651058209392398294887933203625094431173012381970684161403970198376793206832823764648042953118023287825098194558153017567173613320698112509961818815930416903515988885193458072738667385894228792284998920868058257492796104841984443634632449684875602336248270419786232090021609902353043699418491463140934317381436405462531520961836908887070167683964243781405927145635490613031072085103837505101157477041718986106873969655212671546889570350354"); + + /// Gets the ratio of the circumference of a circle to its diameter, specified by the constant, π. + /// This value is accurate to a precision of 1001 decimal digits. + public static BigDecimal Pi => Parse("3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989"); + + /// Gets the number of radians in one turn, specified by the constant, τ. + /// This value is accurate to a precision of 1001 decimal digits. + public static BigDecimal Tau => Parse("6.2831853071795864769252867665590057683943387987502116419498891846156328125724179972560696506842341359642961730265646132941876892191011644634507188162569622349005682054038770422111192892458979098607639288576219513318668922569512964675735663305424038182912971338469206972209086532964267872145204982825474491740132126311763497630418419256585081834307287357851807200226610610976409330427682939038830232188661145407315191839061843722347638652235862102370961489247599254991347037715054497824558763660238982596673467248813132861720427898927904494743814043597218874055410784343525863535047693496369353388102640011362542905271216555715426855155792183472743574429368818024499068602930991707421015845593785178470840399122242580439217280688363196272595495426199210374144226999999967459560999021194634656321926371900489189106938166052850446165066893700705238623763420200062756775057731750664167628412343553382946071965069808575109374623191257277647075751875039155637155610643424536132260038557532223918184328403979"); + + /// + /// Gets the default number format. + /// + private const string DefaultNumberFormat = "G"; + + /// + /// Gets the default number styles for parsing decimal values. + /// + private const NumberStyles DefaultNumberStyles = NumberStyles.Any; + + /// + /// Gets the default culture for formatting and parsing operations. + /// + private static readonly CultureInfo DefaultCulture = CultureInfo.CurrentCulture; + + /// + /// Gets the magnitude by which a remainder must be multiplied in order to obtain ten digits of precision when rounding. + /// + private const long RoundingMagnitude = 10_000_000_000; + + /// + /// Gets the radix, or base, for the type. + /// + static int INumberBase.Radix => 10; + + /// + /// Gets the additive identity for the type, which is zero. + /// + static BigDecimal IAdditiveIdentity.AdditiveIdentity => Zero; + + /// + /// Gets the multiplicative identity for the type, which is one. + /// + static BigDecimal IMultiplicativeIdentity.MultiplicativeIdentity => One; +} diff --git a/OnixLabs.Numerics/BigDecimal.Convert.cs b/OnixLabs.Numerics/BigDecimal.Convert.cs new file mode 100644 index 0000000..fd9c35f --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Convert.cs @@ -0,0 +1,233 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + static bool INumberBase.TryConvertFromChecked(TOther value, out BigDecimal result) + { + return TryConvertFrom(value, out result); + } + + static bool INumberBase.TryConvertFromSaturating(TOther value, out BigDecimal result) + { + return TryConvertFrom(value, out result); + } + + static bool INumberBase.TryConvertFromTruncating(TOther value, out BigDecimal result) + { + return TryConvertFrom(value, out result); + } + + static bool INumberBase.TryConvertToChecked(BigDecimal value, [MaybeNullWhen(false)] out TOther result) + { + return TryConvertTo(value, out result); + } + + static bool INumberBase.TryConvertToSaturating(BigDecimal value, [MaybeNullWhen(false)] out TOther result) + { + return TryConvertTo(value, out result); + } + + static bool INumberBase.TryConvertToTruncating(BigDecimal value, [MaybeNullWhen(false)] out TOther result) + { + return TryConvertTo(value, out result); + } + + private static bool TryConvertFrom(TOther value, out BigDecimal result) where TOther : INumberBase + { + if (typeof(TOther) == typeof(sbyte)) + { + result = (sbyte)(object)value; + return true; + } + + if (typeof(TOther) == typeof(byte)) + { + result = (byte)(object)value; + return true; + } + + if (typeof(TOther) == typeof(short)) + { + result = (short)(object)value; + return true; + } + + if (typeof(TOther) == typeof(ushort)) + { + result = (ushort)(object)value; + return true; + } + + if (typeof(TOther) == typeof(int)) + { + result = (int)(object)value; + return true; + } + + if (typeof(TOther) == typeof(uint)) + { + result = (uint)(object)value; + return true; + } + + if (typeof(TOther) == typeof(long)) + { + result = (long)(object)value; + return true; + } + + if (typeof(TOther) == typeof(ulong)) + { + result = (ulong)(object)value; + return true; + } + + if (typeof(TOther) == typeof(Int128)) + { + result = (Int128)(object)value; + return true; + } + + if (typeof(TOther) == typeof(UInt128)) + { + result = (UInt128)(object)value; + return true; + } + + if (typeof(TOther) == typeof(BigInteger)) + { + result = (BigInteger)(object)value; + return true; + } + + if (typeof(TOther) == typeof(decimal)) + { + result = (decimal)(object)value; + return true; + } + + if (typeof(TOther) == typeof(double)) + { + result = (double)(object)value; + return true; + } + + if (typeof(TOther) == typeof(float)) + { + result = (float)(object)value; + return true; + } + + result = default; + return false; + } + + private static bool TryConvertTo(BigDecimal value, [MaybeNullWhen(false)] out TOther result) where TOther : INumberBase + { + if (typeof(TOther) == typeof(sbyte)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(byte)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(short)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(ushort)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(int)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(uint)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(long)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(ulong)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(Int128)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(UInt128)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(BigInteger)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(decimal)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(double)) + { + result = (TOther)(object)value; + return true; + } + + if (typeof(TOther) == typeof(float)) + { + result = (TOther)(object)value; + return true; + } + + result = default; + return false; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Convertible.Explicit.cs b/OnixLabs.Numerics/BigDecimal.Convertible.Explicit.cs new file mode 100644 index 0000000..1e04241 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Convertible.Explicit.cs @@ -0,0 +1,207 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator BigInteger(BigDecimal value) + { + return value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator sbyte(BigDecimal value) + { + CheckIntegerOverflow(value, sbyte.MinValue, sbyte.MaxValue); + return (sbyte)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator byte(BigDecimal value) + { + CheckIntegerOverflow(value, byte.MinValue, byte.MaxValue); + return (byte)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator short(BigDecimal value) + { + CheckIntegerOverflow(value, short.MinValue, short.MaxValue); + return (short)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator ushort(BigDecimal value) + { + CheckIntegerOverflow(value, ushort.MinValue, ushort.MaxValue); + return (ushort)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator int(BigDecimal value) + { + CheckIntegerOverflow(value, int.MinValue, int.MaxValue); + return (int)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator uint(BigDecimal value) + { + CheckIntegerOverflow(value, uint.MinValue, uint.MaxValue); + return (uint)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator long(BigDecimal value) + { + CheckIntegerOverflow(value, long.MinValue, long.MaxValue); + return (long)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator ulong(BigDecimal value) + { + CheckIntegerOverflow(value, ulong.MinValue, ulong.MaxValue); + return (ulong)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator Int128(BigDecimal value) + { + CheckIntegerOverflow(value, Int128.MinValue, Int128.MaxValue); + return (Int128)value.number.Integer; + } + + /// + /// Converts the integral value of the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the integral value of the specified value. + public static explicit operator UInt128(BigDecimal value) + { + CheckIntegerOverflow(value, UInt128.MinValue, UInt128.MaxValue); + return (UInt128)value.number.Integer; + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value the specified value. + public static explicit operator float(BigDecimal value) + { + if (value < float.MinValue || value > float.MaxValue) + { + throw new OverflowException($"Value was either too large or too small for the specified type: {nameof(Single)}."); + } + + return Convert.ToSingle(value.ToString("E")); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value the specified value. + public static explicit operator double(BigDecimal value) + { + if (value < double.MinValue || value > double.MaxValue) + { + throw new OverflowException($"Value was either too large or too small for the specified type: {nameof(Double)}."); + } + + return Convert.ToDouble(value.ToString("E")); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value the specified value. + public static explicit operator decimal(BigDecimal value) + { + if (value < decimal.MinValue || value > decimal.MaxValue) + { + throw new OverflowException($"Value was either too large or too small for the specified type: {nameof(Decimal)}."); + } + + return Convert.ToDecimal(value.ToString("E")); + } + + /// + /// Checks whether the integral value of the specified + /// is within the bounds of the specified minimum and maximum values. + /// + /// The value to check. + /// The minimum bound value. + /// The maximum bound value. + /// The underlying value. + /// if the integral value of the specified + /// value is not within the bounds of the specified minimum and maximum value. + private static void CheckIntegerOverflow(BigDecimal value, T min, T max) where T : IBinaryInteger + { + BigInteger checkedMin = BigInteger.CreateChecked(min); + BigInteger checkedMax = BigInteger.CreateChecked(max); + + if (value.number.Integer < checkedMin || value.number.Integer > checkedMax) + { + throw new OverflowException($"Value was either too large or too small for the specified type: {typeof(T).Name}."); + } + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Convertible.Implicit.cs b/OnixLabs.Numerics/BigDecimal.Convertible.Implicit.cs new file mode 100644 index 0000000..b9d0857 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Convertible.Implicit.cs @@ -0,0 +1,161 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(BigInteger value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(sbyte value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(byte value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(short value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(ushort value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(int value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(uint value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(long value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(ulong value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(Int128 value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(UInt128 value) + { + return new BigDecimal(value, default, ScaleMode.Integral); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(float value) + { + return new BigDecimal(value); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(double value) + { + return new BigDecimal(value); + } + + /// + /// Converts the specified value to a value. + /// + /// The value to convert. + /// Returns a value representing the specified value. + public static implicit operator BigDecimal(decimal value) + { + return new BigDecimal(value); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Convertible.cs b/OnixLabs.Numerics/BigDecimal.Convertible.cs new file mode 100644 index 0000000..6bd8a52 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Convertible.cs @@ -0,0 +1,191 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal : IConvertible +{ + /// + /// Gets the for the current instance. + /// + /// Returns the enumerated constant that is the of the class or value type that implements this interface. + TypeCode IConvertible.GetTypeCode() + { + return TypeCode.Object; + } + + /// + /// Converts the value of this instance to an equivalent 8-bit signed integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns an 8-bit signed integer equivalent to the value of this instance. + sbyte IConvertible.ToSByte(IFormatProvider? provider) + { + return (sbyte)this; + } + + /// + /// Converts the value of this instance to an equivalent 8-bit unsigned integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns an 8-bit unsigned integer equivalent to the value of this instance. + byte IConvertible.ToByte(IFormatProvider? provider) + { + return (byte)this; + } + + /// + /// Converts the value of this instance to an equivalent 16-bit signed integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a 16-bit signed integer equivalent to the value of this instance. + short IConvertible.ToInt16(IFormatProvider? provider) + { + return (short)this; + } + + /// + /// Converts the value of this instance to an equivalent 32-bit signed integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a 32-bit signed integer equivalent to the value of this instance. + int IConvertible.ToInt32(IFormatProvider? provider) + { + return (int)this; + } + + /// + /// Converts the value of this instance to an equivalent 64-bit signed integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a 64-bit signed integer equivalent to the value of this instance. + long IConvertible.ToInt64(IFormatProvider? provider) + { + return (long)this; + } + + /// + /// Converts the value of this instance to an equivalent 16-bit unsigned integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a 16-bit unsigned integer equivalent to the value of this instance. + ushort IConvertible.ToUInt16(IFormatProvider? provider) + { + return (ushort)this; + } + + /// + /// Converts the value of this instance to an equivalent 32-bit unsigned integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a 32-bit unsigned integer equivalent to the value of this instance. + uint IConvertible.ToUInt32(IFormatProvider? provider) + { + return (uint)this; + } + + /// + /// Converts the value of this instance to an equivalent 64-bit unsigned integer using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a 64-bit unsigned integer equivalent to the value of this instance. + ulong IConvertible.ToUInt64(IFormatProvider? provider) + { + return (ulong)this; + } + + /// + /// Converts the value of this instance to an equivalent single-precision floating-point number using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a single-precision floating-point number equivalent to the value of this instance. + float IConvertible.ToSingle(IFormatProvider? provider) + { + return (float)this; + } + + /// + /// Converts the value of this instance to an equivalent double-precision floating-point number using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a double-precision floating-point number equivalent to the value of this instance. + double IConvertible.ToDouble(IFormatProvider? provider) + { + return (double)this; + } + + /// + /// Converts the value of this instance to an equivalent number using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a number equivalent to the value of this instance. + decimal IConvertible.ToDecimal(IFormatProvider? provider) + { + return (decimal)this; + } + + /// + /// Converts the value of this instance to an equivalent using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a instance equivalent to the value of this instance. + DateTime IConvertible.ToDateTime(IFormatProvider? provider) + { + long binary = (long)UnscaledValue; + return DateTime.FromBinary(binary); + } + + /// + /// Converts the value of this instance to an equivalent value using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a value equivalent to the value of this instance. + bool IConvertible.ToBoolean(IFormatProvider? provider) + { + return !IsZero(this); + } + + /// + /// Converts the value of this instance to an equivalent Unicode character using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a Unicode character equivalent to the value of this instance. + char IConvertible.ToChar(IFormatProvider? provider) + { + return (char)this; + } + + /// + /// Converts the value of this instance to an equivalent using the specified culture-specific formatting information. + /// + /// An interface implementation that supplies culture-specific formatting information. + /// Returns a instance equivalent to the value of this instance. + string IConvertible.ToString(IFormatProvider? provider) + { + return ToString(DefaultNumberFormat, provider); + } + + /// + /// Converts the value of this instance to an of the specified that has an equivalent value, using the specified culture-specific formatting information. + /// + /// The to which the value of this instance is converted + /// An interface implementation that supplies culture-specific formatting information. + /// Returns an instance of type conversionType whose value is equivalent to the value of this instance. + object IConvertible.ToType(Type conversionType, IFormatProvider? provider) + { + return Convert.ChangeType(this, conversionType, provider); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Equatable.cs b/OnixLabs.Numerics/BigDecimal.Equatable.cs new file mode 100644 index 0000000..9ab9859 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Equatable.cs @@ -0,0 +1,122 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Compares two instances of to determine whether their values are equal. + /// This method implements the comparer. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool Equals(BigDecimal left, BigDecimal right) + { + return Equals(left, right, BigDecimalEqualityComparer.Strict); + } + + /// + /// Compares two instances of to determine whether their values are equal. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// The equality comparer to use to determine equality. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool Equals(BigDecimal left, BigDecimal right, BigDecimalEqualityComparer comparer) + { + return comparer.Equals(left, right); + } + + /// + /// Compares the current instance of with the specified other instance of . + /// This method implements the comparer. + /// + /// The other instance of to compare with the current instance. + /// Returns true if the current instance is equal to the specified other instance; otherwise, false. + public bool Equals(BigDecimal other) + { + return Equals(this, other); + } + + /// + /// Compares the current instance of with the specified other instance of . + /// + /// The other instance of to compare with the current instance. + /// The equality comparer to use to determine equality. + /// Returns true if the current instance is equal to the specified other instance; otherwise, false. + public bool Equals(BigDecimal other, BigDecimalEqualityComparer comparer) + { + return Equals(this, other, comparer); + } + + /// + /// Checks for equality between this instance and another object. + /// This method implements the comparer. + /// + /// The object to check for equality. + /// Returns true if the object is equal to this instance; otherwise, false. + public override bool Equals(object? obj) + { + return obj is BigDecimal other && Equals(other); + } + + /// + /// Checks for equality between this instance and another object. + /// + /// The object to check for equality. + /// The equality comparer to use to determine equality. + /// Returns true if the object is equal to this instance; otherwise, false. + public bool Equals(object? obj, BigDecimalEqualityComparer comparer) + { + return obj is BigDecimal other && Equals(other, comparer); + } + + /// + /// Serves as a hash code function for this instance. + /// This method implements the comparer. + /// + /// A hash code for this instance. + public override int GetHashCode() + { + return BigDecimalEqualityComparer.Strict.GetHashCode(this); + } + + /// + /// Compares two instances of to determine whether their values are equal. + /// This method implements the comparer. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool operator ==(BigDecimal left, BigDecimal right) + { + return Equals(left, right, BigDecimalEqualityComparer.Semantic); + } + + /// + /// Compares two instances of to determine whether their values are not equal. + /// This method implements the comparer. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the two specified instances are not equal; otherwise, false. + public static bool operator !=(BigDecimal left, BigDecimal right) + { + return Equals(left, right, BigDecimalEqualityComparer.Semantic); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Format.cs b/OnixLabs.Numerics/BigDecimal.Format.cs new file mode 100644 index 0000000..1d67893 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Format.cs @@ -0,0 +1,45 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Tries to format the value of the current instance into the provided span of characters. + /// + /// The span in which to write this instance's value formatted as a span of characters. + /// When this method returns, contains the number of characters that were written in . + /// A span containing the characters that represent a standard or custom format string that defines the acceptable format for . + /// An optional object that supplies culture-specific formatting information for . + /// Returns if the formatting was successful; otherwise, . + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + CultureInfo info = provider as CultureInfo ?? DefaultCulture; + string formatted = ToString(format, info); + + if (formatted.Length > destination.Length) + { + charsWritten = 0; + return false; + } + + formatted.AsSpan().CopyTo(destination); + charsWritten = formatted.Length; + return true; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Get.cs b/OnixLabs.Numerics/BigDecimal.Get.cs new file mode 100644 index 0000000..ed81ddb --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Get.cs @@ -0,0 +1,40 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + int IFloatingPoint.GetExponentByteCount() + { + return sizeof(int); + } + + int IFloatingPoint.GetExponentShortestBitLength() + { + return sizeof(int) - int.LeadingZeroCount(number.Exponent); + } + + int IFloatingPoint.GetSignificandBitLength() + { + return number.Significand.ToByteArray().Length * 8; + } + + int IFloatingPoint.GetSignificandByteCount() + { + return number.Significand.ToByteArray().Length; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Is.cs b/OnixLabs.Numerics/BigDecimal.Is.cs new file mode 100644 index 0000000..aee2f78 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Is.cs @@ -0,0 +1,190 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Determines if a value represents an integral number. + /// + /// The value to be checked. + /// Returns true if the value is an integer; otherwise, false. + public static bool IsInteger(BigDecimal value) + { + return value.number.Fraction == BigInteger.Zero; + } + + /// + /// Determines if a value represents an even integral number. + /// + /// The value to be checked. + /// Returns true if the value is an even integer; otherwise, false. + public static bool IsEvenInteger(BigDecimal value) + { + return IsInteger(value) && BigInteger.IsEvenInteger(value.number.Integer); + } + + /// + /// Determines if a value represents an odd integral number. + /// + /// The value to be checked. + /// Returns true if the value is an odd integer; otherwise, false. + public static bool IsOddInteger(BigDecimal value) + { + return IsInteger(value) && BigInteger.IsOddInteger(value.number.Integer); + } + + /// + /// Determines if a value is negative. + /// + /// The value to be checked. + /// Returns true if the value is negative; otherwise, false. + public static bool IsNegative(BigDecimal value) + { + return BigInteger.IsNegative(value.UnscaledValue); + } + + /// + /// Determines if a value is positive. + /// + /// The value to be checked. + /// Returns true if the value is positive; otherwise, false. + public static bool IsPositive(BigDecimal value) + { + return BigInteger.IsPositive(value.UnscaledValue); + } + + /// + /// Determines if a value is zero. + /// + /// The value to be checked. + /// Returns true if the value is zero; otherwise, false. + public static bool IsZero(BigDecimal value) + { + return value.UnscaledValue == BigInteger.Zero; + } + + /// + /// Determines if a value is in its canonical representation. + /// + /// The value to be checked. + /// Returns true if value is in its canonical representation; otherwise, false. + static bool INumberBase.IsCanonical(BigDecimal value) + { + return true; + } + + /// + /// Determines if a value represents a complex number. + /// + /// The value to be checked. + /// Returns true if value is a complex number; otherwise, false. + static bool INumberBase.IsComplexNumber(BigDecimal value) + { + return false; + } + + /// + /// Determines if a value is finite. + /// + /// The value to be checked. + /// Returns true if value is finite; otherwise, false. + static bool INumberBase.IsFinite(BigDecimal value) + { + return true; + } + + /// + /// Determines if a value represents a pure imaginary number. + /// + /// The value to be checked. + /// Returns true if value is a pure imaginary number; otherwise, false. + static bool INumberBase.IsImaginaryNumber(BigDecimal value) + { + return false; + } + + /// + /// Determines if a value is infinite. + /// + /// The value to be checked. + /// Returns true if value is infinite; otherwise, false. + static bool INumberBase.IsInfinity(BigDecimal value) + { + return false; + } + + /// + /// Determines if a value is NaN. + /// + /// The value to be checked. + /// Returns true if value is NaN; otherwise, false. + static bool INumberBase.IsNaN(BigDecimal value) + { + return false; + } + + /// + /// Determines if a value is negative infinity. + /// + /// The value to be checked. + /// Returns true if value is negative infinity; otherwise, false. + static bool INumberBase.IsNegativeInfinity(BigDecimal value) + { + return false; + } + + /// + /// Determines if a value is normal. + /// + /// The value to be checked. + /// Returns true if value is normal; otherwise, false. + static bool INumberBase.IsNormal(BigDecimal value) + { + return true; + } + + /// + /// Determines if a value is positive infinity. + /// + /// The value to be checked. + /// Returns true if value is positive infinity; otherwise, false. + static bool INumberBase.IsPositiveInfinity(BigDecimal value) + { + return false; + } + + /// + /// Determines if a value represents a real number. + /// + /// The value to be checked. + /// Returns true if value is a real number; otherwise, false + static bool INumberBase.IsRealNumber(BigDecimal value) + { + return true; + } + + /// + /// Determines if a value is subnormal. + /// + /// The value to be checked. + /// Returns true if value is subnormal; otherwise, false. + static bool INumberBase.IsSubnormal(BigDecimal value) + { + return false; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Parse.cs b/OnixLabs.Numerics/BigDecimal.Parse.cs new file mode 100644 index 0000000..7f30ada --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Parse.cs @@ -0,0 +1,169 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Parses the specified value into a value. + /// + /// The value to parse. + /// An object that provides culture-specific information about the specified value. + /// Returns a new instance parsed from the specified value. + public static BigDecimal Parse(string value, IFormatProvider? provider = null) + { + return Parse(value.AsSpan(), provider); + } + + /// + /// Parses the specified value into a value. + /// + /// The value to parse. + /// A bitwise combination of number styles that can be present in the specified value. + /// An object that provides culture-specific information about the specified value. + /// Returns a new instance parsed from the specified value. + public static BigDecimal Parse(string value, NumberStyles style, IFormatProvider? provider = null) + { + return Parse(value.AsSpan(), style, provider); + } + + /// + /// Parses the specified value into a value. + /// + /// The value to parse. + /// An object that provides culture-specific information about the specified value. + /// Returns a new instance parsed from the specified value. + public static BigDecimal Parse(ReadOnlySpan value, IFormatProvider? provider = null) + { + return Parse(value, DefaultNumberStyles, provider); + } + + /// + /// Parses the specified value into a value. + /// + /// The value to parse. + /// A bitwise combination of number styles that can be present in the specified value. + /// An object that provides culture-specific information about the specified value. + /// Returns a new instance parsed from the specified value. + public static BigDecimal Parse(ReadOnlySpan value, NumberStyles style, IFormatProvider? provider = null) + { + CultureInfo info = provider as CultureInfo ?? DefaultCulture; + if (TryParse(value, style, info, out BigDecimal result)) return result; + throw new FormatException($"The input string '{value}' was not in a correct format."); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, out BigDecimal result) + { + return TryParse(value.AsSpan(), out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// An object that provides culture-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, IFormatProvider? provider, out BigDecimal result) + { + return TryParse(value.AsSpan(), provider, out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// A bitwise combination of number styles that can be present in the specified value. + /// An object that provides culture-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, NumberStyles style, IFormatProvider? provider, out BigDecimal result) + { + return TryParse(value.AsSpan(), style, provider, out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, out BigDecimal result) + { + return TryParse(value, DefaultCulture, out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// An object that provides culture-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out BigDecimal result) + { + return TryParse(value, DefaultNumberStyles, provider, out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// A bitwise combination of number styles that can be present in the specified value. + /// An object that provides culture-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, NumberStyles style, IFormatProvider? provider, out BigDecimal result) + { + CultureInfo info = provider as CultureInfo ?? DefaultCulture; + NumberInfoParser parser = new(style, info); + + if (parser.TryParse(value, out NumberInfo numberInfo)) + { + result = new BigDecimal(numberInfo.UnscaledValue, numberInfo.Scale); + return true; + } + + result = default; + return false; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.To.cs b/OnixLabs.Numerics/BigDecimal.To.cs new file mode 100644 index 0000000..f453a5b --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.To.cs @@ -0,0 +1,103 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// + /// Gets a representing the current . + /// + /// Returns a representing the current . + public NumberInfo ToNumberInfo() + { + return number; + } + + /// + /// Formats the value of the current instance using the default format. + /// + /// The value of the current instance in the default format. + public override string ToString() + { + return ToString(DefaultNumberFormat, DefaultCulture); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(string? format, IFormatProvider? formatProvider = null) + { + return ToString((format ?? DefaultNumberFormat).AsSpan(), formatProvider); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + { + CultureInfo info = formatProvider as CultureInfo ?? DefaultCulture; + + if (!TryGetScaledNumberInfo(format, info.NumberFormat, out NumberInfo value)) return format.ToString(); + + NumberInfoFormatter formatter = new(value, info, ['C', 'D', 'E', 'F', 'G', 'N', 'P']); + return formatter.Format(format); + } + + /// + /// Attempts to obtain a value that is scaled by either using a custom + /// scale that is specified by the format, or by using the default scale for the specified format. + /// + /// The format specifier from which to obtain the desired scale. + /// The number format of the target culture that determines default scales for specific formats. + /// The value with a correctly applied scale. + /// Returns if the scale is applied correctly; otherwise, false. + private bool TryGetScaledNumberInfo(ReadOnlySpan format, NumberFormatInfo numberFormat, out NumberInfo result) + { + const MidpointRounding mode = MidpointRounding.AwayFromZero; + char specifier = format.IsEmpty || format.IsWhiteSpace() ? NumberInfoFormatter.DefaultFormat : format[0]; + + if (format.Length > 1) + { + if (!int.TryParse(format[1..], out int scale)) + { + result = default; + return false; + } + + result = SetScale(scale).number; + return true; + } + + result = char.ToUpperInvariant(specifier) switch + { + 'C' => SetScale(numberFormat.CurrencyDecimalDigits, mode).ToNumberInfo(), + 'F' => SetScale(numberFormat.NumberDecimalDigits, mode).ToNumberInfo(), + 'N' => SetScale(numberFormat.NumberDecimalDigits, mode).ToNumberInfo(), + 'P' => Multiply(this, 100).SetScale(numberFormat.PercentDecimalDigits, mode).ToNumberInfo(), + _ => ToNumberInfo() + }; + + return true; + } +} diff --git a/OnixLabs.Numerics/BigDecimal.Write.cs b/OnixLabs.Numerics/BigDecimal.Write.cs new file mode 100644 index 0000000..3a1d89b --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.Write.cs @@ -0,0 +1,76 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Buffers.Binary; +using System.Numerics; + +namespace OnixLabs.Numerics; + +public readonly partial struct BigDecimal +{ + /// Tries to write the current exponent, in big-endian format, to a given span. + /// The span to which the current exponent should be written. + /// When this method returns, contains the number of bytes written to . + /// Returns if the exponent was successfully written to ; otherwise, . + bool IFloatingPoint.TryWriteExponentBigEndian(Span destination, out int bytesWritten) + { + const int size = sizeof(int); + + if (destination.Length >= size && BinaryPrimitives.TryWriteInt32BigEndian(destination, number.Exponent)) + { + bytesWritten = size; + return true; + } + + bytesWritten = 0; + return false; + } + + /// Tries to write the current exponent, in little-endian format, to a given span. + /// The span to which the current exponent should be written. + /// When this method returns, contains the number of bytes written to . + /// Returns if the exponent was successfully written to ; otherwise, . + bool IFloatingPoint.TryWriteExponentLittleEndian(Span destination, out int bytesWritten) + { + const int size = sizeof(int); + + if (destination.Length >= size && BinaryPrimitives.TryWriteInt32LittleEndian(destination, number.Exponent)) + { + bytesWritten = size; + return true; + } + + bytesWritten = 0; + return false; + } + + /// Tries to write the current significand, in big-endian format, to a given span. + /// The span to which the current significand should be written. + /// When this method returns, contains the number of bytes written to . + /// Returns if the significand was successfully written to ; otherwise, . + bool IFloatingPoint.TryWriteSignificandBigEndian(Span destination, out int bytesWritten) + { + return number.Significand.TryWriteBytes(destination, out bytesWritten, isBigEndian: true); + } + + /// Tries to write the current significand, in little-endian format, to a given span. + /// The span to which the current significand should be written. + /// When this method returns, contains the number of bytes written to . + /// Returns if the significand was successfully written to ; otherwise, . + bool IFloatingPoint.TryWriteSignificandLittleEndian(Span destination, out int bytesWritten) + { + return number.Significand.TryWriteBytes(destination, out bytesWritten); + } +} diff --git a/OnixLabs.Numerics/BigDecimal.cs b/OnixLabs.Numerics/BigDecimal.cs new file mode 100644 index 0000000..629e230 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimal.cs @@ -0,0 +1,82 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +/// +/// Represents an arbitrarily large signed decimal. +/// +public readonly partial struct BigDecimal : IFloatingPoint +{ + /// + /// The underlying that represents the current value. + /// + private readonly NumberInfo number; + + /// + /// Initializes a new instance of the struct. + /// + /// The unscaled integer value from which to construct a value. + /// The scale of the value. + /// The scale mode that determines how the specified value should be scaled. + public BigDecimal(BigInteger value, int scale = default, ScaleMode mode = default) + { + Require(scale >= 0, "Scale must be greater than or equal to zero.", nameof(scale)); + RequireIsDefined(mode, nameof(mode)); + number = value.ToNumberInfo(scale, mode); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The floating-point value from which to construct a value. + /// The conversion mode that determines whether the floating-point value should be converted from its binary or decimal representation. + public BigDecimal(float value, ConversionMode mode = default) + { + RequireIsDefined(mode, nameof(mode)); + number = value.ToNumberInfo(mode); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The floating-point value from which to construct a value. + /// The conversion mode that determines whether the floating-point value should be converted from its binary or decimal representation. + public BigDecimal(double value, ConversionMode mode = default) + { + RequireIsDefined(mode, nameof(mode)); + number = value.ToNumberInfo(mode); + } + + /// + /// Initializes a new instance of the struct. + /// + /// The decimal value from which to construct a value. + public BigDecimal(decimal value) + { + number = value.ToNumberInfo(); + } + + /// + /// Gets the unscaled value of the current value. + /// + public BigInteger UnscaledValue => number.UnscaledValue; + + /// + /// Gets the scale of the current value. + /// + public int Scale => number.Scale; +} diff --git a/OnixLabs.Numerics/BigDecimalEqualityComparer.cs b/OnixLabs.Numerics/BigDecimalEqualityComparer.cs new file mode 100644 index 0000000..ac29578 --- /dev/null +++ b/OnixLabs.Numerics/BigDecimalEqualityComparer.cs @@ -0,0 +1,117 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections; +using System.Collections.Generic; + +namespace OnixLabs.Numerics; + +/// +/// Represents an equality comparer for comparing values. +/// +public abstract class BigDecimalEqualityComparer : IEqualityComparer, IEqualityComparer +{ + /// + /// Gets an equality comparer that strictly compares values. + /// + public static readonly BigDecimalEqualityComparer Strict = new BigDecimalStrictEqualityComparer(); + + /// + /// Gets an equality comparer that semantically compares values. + /// + public static readonly BigDecimalEqualityComparer Semantic = new BigDecimalSemanticEqualityComparer(); + + /// + /// Prevents a default instance of the class from being created. + /// + private BigDecimalEqualityComparer() + { + } + + /// Determines whether the specified values are equal. + /// The first object of type to compare. + /// The second object of type to compare. + /// Returns if the specified values are equal; otherwise, . + public abstract bool Equals(BigDecimal x, BigDecimal y); + + /// Returns a hash code for the specified value. + /// The value for which a hash code is to be returned. + /// Returns a hash code for the specified value. + public abstract int GetHashCode(BigDecimal obj); + + /// Determines whether the specified objects are equal. + /// The first object to compare. + /// The second object to compare. + /// Returns if the specified objects are both of type and are equal; otherwise, . + public new bool Equals(object? x, object? y) + { + return x is BigDecimal left && y is BigDecimal right && Equals(left, right); + } + + /// Returns a hash code for the specified object. + /// The for which a hash code is to be returned. + /// A hash code for the specified object. + public int GetHashCode(object obj) + { + return obj is BigDecimal value ? GetHashCode(value) : obj.GetHashCode(); + } + + /// + /// Represents an equality comparer that compares values using strict equality. + /// Strict equality is determined by comparing and properties. + /// + private sealed class BigDecimalStrictEqualityComparer : BigDecimalEqualityComparer + { + /// Determines whether the specified values are equal. + /// The first object of type to compare. + /// The second object of type to compare. + /// Returns if the specified values are equal; otherwise, . + public override bool Equals(BigDecimal x, BigDecimal y) + { + return NumberInfoEqualityComparer.Strict.Equals(x.ToNumberInfo(), y.ToNumberInfo()); + } + + /// Returns a hash code for the specified object. + /// The for which a hash code is to be returned. + /// A hash code for the specified object. + public override int GetHashCode(BigDecimal obj) + { + return NumberInfoEqualityComparer.Strict.GetHashCode(obj.ToNumberInfo()); + } + } + + /// + /// Represents an equality comparer that compares values using semantic equality. + /// Semantic equality is determined by comparing that values are equivalent, even when their scale differs. + /// + private sealed class BigDecimalSemanticEqualityComparer : BigDecimalEqualityComparer + { + /// Determines whether the specified values are equal. + /// The first object of type to compare. + /// The second object of type to compare. + /// Returns if the specified values are equal; otherwise, . + public override bool Equals(BigDecimal x, BigDecimal y) + { + return NumberInfoEqualityComparer.Semantic.Equals(x.ToNumberInfo(), y.ToNumberInfo()); + } + + /// Returns a hash code for the specified object. + /// The for which a hash code is to be returned. + /// A hash code for the specified object. + public override int GetHashCode(BigDecimal obj) + { + return NumberInfoEqualityComparer.Semantic.GetHashCode(obj.ToNumberInfo()); + } + } +} diff --git a/OnixLabs.Numerics/BigDecimalOrdinalityComparer.cs b/OnixLabs.Numerics/BigDecimalOrdinalityComparer.cs new file mode 100644 index 0000000..b3e67ce --- /dev/null +++ b/OnixLabs.Numerics/BigDecimalOrdinalityComparer.cs @@ -0,0 +1,114 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OnixLabs.Numerics; + +/// +/// Represents an ordinal comparer for comparing values. +/// +public sealed class BigDecimalOrdinalityComparer : IComparer, IComparer +{ + /// + /// Gets the default ordinal comparer for comparing values. + /// + public static readonly BigDecimalOrdinalityComparer Default = new(); + + /// + /// Prevents a default instance of the class from being created. + /// + private BigDecimalOrdinalityComparer() + { + } + + /// Compares two values and returns a value indicating whether one is less than, equal to, or greater than the other. + /// The first value to compare. + /// The second value to compare. + /// Returns a signed integer that indicates the relative order of the values being compared. + public int Compare(BigDecimal x, BigDecimal y) + { + return NumberInfoOrdinalityComparer.Default.Compare(x.ToNumberInfo(), y.ToNumberInfo()); + } + + /// Compares two values and returns a value indicating whether one is less than, equal to, or greater than the other. + /// The first value to compare. + /// The second value to compare. + /// Returns a signed integer that indicates the relative order of the values being compared. + /// If either or are not of type . + public int Compare(object? x, object? y) + { + if (x is not BigDecimal left) throw new ArgumentException($"Argument must be of type {nameof(BigDecimal)}", nameof(x)); + if (y is not BigDecimal right) throw new ArgumentException($"Argument must be of type {nameof(BigDecimal)}", nameof(y)); + + return Compare(left, right); + } + + /// + /// Determines whether the left-hand value is equal to the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is equal to the right-hand value; otherwise, . + public bool IsEqual(BigDecimal left, BigDecimal right) + { + return Compare(left, right) is 0; + } + + /// + /// Determines whether the left-hand value is greater than the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is greater than the right-hand value; otherwise, . + public bool IsGreaterThan(BigDecimal left, BigDecimal right) + { + return Compare(left, right) is 1; + } + + /// + /// Determines whether the left-hand value is greater than, or equal to the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is greater than, or equal to the right-hand value; otherwise, . + public bool IsGreaterThanOrEqual(BigDecimal left, BigDecimal right) + { + return Compare(left, right) is 0 or 1; + } + + /// + /// Determines whether the left-hand value is less than the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is less than the right-hand value; otherwise, . + public bool IsLessThan(BigDecimal left, BigDecimal right) + { + return Compare(left, right) is -1; + } + + /// + /// Determines whether the left-hand value is less than, or equal to the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is less than, or equal to the right-hand value; otherwise, . + public bool IsLessThanOrEqual(BigDecimal left, BigDecimal right) + { + return Compare(left, right) is -1 or 0; + } +} diff --git a/OnixLabs.Numerics/ConversionMode.cs b/OnixLabs.Numerics/ConversionMode.cs new file mode 100644 index 0000000..cbdd173 --- /dev/null +++ b/OnixLabs.Numerics/ConversionMode.cs @@ -0,0 +1,31 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Numerics; + +/// +/// Specifies IEEE 754 binary floating-point conversion modes. +/// +public enum ConversionMode +{ + /// + /// Specifies that IEEE 754 binary floating-point values will be converted from their decimal representation. + /// + Decimal, + + /// + /// Specifies that IEEE 754 binary floating-point values will be converted from their binary representation. + /// + Binary +} diff --git a/OnixLabs.Numerics/GenericMath.cs b/OnixLabs.Numerics/GenericMath.cs new file mode 100644 index 0000000..fa663a3 --- /dev/null +++ b/OnixLabs.Numerics/GenericMath.cs @@ -0,0 +1,63 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; +using System.Numerics; + +namespace OnixLabs.Numerics; + +/// +/// Provides generic mathematical functions. +/// +public static class GenericMath +{ + /// + /// Computes the delta, or difference between the specified numbers. + /// + /// The left-hand number from which to compute the delta. + /// The right-hand number from which to compute the delta. + /// The underlying type. + /// Returns the delta, or difference between the specified numbers. + public static T Delta(T left, T right) where T : INumberBase + { + return T.Abs(left - right); + } + + /// + /// Obtains the length of the integral component of the specified value. + /// + /// The value from which to obtain the length of the integral component. + /// The underlying type. + /// Returns the length of the integral component of the specified value. + public static int IntegerLength(T value) where T : INumberBase + { + BigInteger integer = BigInteger.Abs(BigInteger.CreateTruncating(value)); + return integer.ToString("G", CultureInfo.InvariantCulture).Length; + } + + /// + /// Obtains the minimum and maximum values from the specified left-hand and right-hand values. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// The underlying type. + /// Returns the minimum and maximum values from the specified left-hand and right-hand values. + public static (T Min, T Max) MinMax(T left, T right) where T : INumber + { + T min = T.Min(left, right); + T max = T.Max(left, right); + + return (min, max); + } +} diff --git a/OnixLabs.Numerics/Ieee754Converter.cs b/OnixLabs.Numerics/Ieee754Converter.cs new file mode 100644 index 0000000..3df5c91 --- /dev/null +++ b/OnixLabs.Numerics/Ieee754Converter.cs @@ -0,0 +1,228 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; +using System.Linq; +using System.Numerics; +using OnixLabs.Core; +using OnixLabs.Core.Linq; + +namespace OnixLabs.Numerics; + +/// +/// Represents conversion of IEEE 754 binary floating-point numbers. +/// +internal static class Ieee754Converter +{ + /// + /// Converts an IEEE 754 single-precision binary floating-point number. + /// + /// The value to convert. + /// The mode that specifies whether the value should be converted using its binary or decimal representation. + /// Returns a containing the unscaled value and scale. + public static NumberInfo Convert(float value, ConversionMode mode) + { + RequireRealNumber(value); + RequireIsDefined(mode, nameof(mode)); + + if (IsZeroOrOne(value, out NumberInfo result)) return result; + + return mode switch + { + ConversionMode.Binary => ConvertFromBinary(value), + ConversionMode.Decimal => ConvertFromDecimal(value), + _ => throw new ArgumentOutOfRangeException(nameof(mode)) + }; + } + + /// + /// Converts an IEEE 754 double-precision binary floating-point number. + /// + /// The value to convert. + /// The mode that specifies whether the value should be converted using its binary or decimal representation. + /// Returns a containing the unscaled value and scale. + public static NumberInfo Convert(double value, ConversionMode mode) + { + RequireRealNumber(value); + RequireIsDefined(mode, nameof(mode)); + + if (IsZeroOrOne(value, out NumberInfo result)) return result; + + return mode switch + { + ConversionMode.Binary => ConvertFromBinary(value), + ConversionMode.Decimal => ConvertFromDecimal(value), + _ => throw new ArgumentOutOfRangeException(nameof(mode)) + }; + } + + /// + /// Converts an IEEE 754 single-precision binary floating-point number using its binary representation. + /// + /// The value to convert. + /// Returns a containing the unscaled value and scale. + private static NumberInfo ConvertFromBinary(float value) + { + const int significandBits = 23; + const int exponentBits = 8; + const int significandMask = (1 << significandBits) - 1; + const int exponentMask = (1 << exponentBits) - 1; + + int bits = BitConverter.SingleToInt32Bits(value); + int significand = bits & significandMask; + int exponent = (bits >> significandBits) & exponentMask; + bool denormalizedExponent = exponent is 0; + + exponent -= denormalizedExponent ? 126 : 127; + exponent -= significandBits; + + if (!denormalizedExponent) significand |= 1 << significandBits; + + while (exponent < 0 && (significand & 1) is 0) + { + exponent++; + significand >>= 1; + } + + BigInteger unscaledValue = bits < 0 ? -significand : significand; + int scale = 0; + + if (exponent < 0) + { + scale = int.Abs(exponent); + unscaledValue *= BigInteger.Pow(5, scale); + } + else + { + unscaledValue <<= exponent; + } + + return new NumberInfo(unscaledValue, scale); + } + + /// + /// Converts an IEEE 754 double-precision binary floating-point number using its binary representation. + /// + /// The value to convert. + /// Returns a containing the unscaled value and scale. + private static NumberInfo ConvertFromBinary(double value) + { + const int significandBits = 52; + const int exponentBits = 11; + const long significandMask = (1L << significandBits) - 1; + const long exponentMask = (1L << exponentBits) - 1; + + long bits = BitConverter.DoubleToInt64Bits(value); + long significand = bits & significandMask; + long exponent = (bits >> significandBits) & exponentMask; + bool denormalizedExponent = exponent is 0; + + exponent -= denormalizedExponent ? 1022 : 1023; + exponent -= significandBits; + + if (!denormalizedExponent) significand |= 1L << significandBits; + + while (exponent < 0 && (significand & 1) is 0) + { + exponent++; + significand >>= 1; + } + + BigInteger unscaledValue = bits < 0 ? -significand : significand; + int scale = 0; + + if (exponent < 0) + { + scale = (int)long.Abs(exponent); + unscaledValue *= BigInteger.Pow(5, scale); + } + else + { + unscaledValue <<= (int)exponent; + } + + return new NumberInfo(unscaledValue, scale); + } + + /// + /// Converts an IEEE 754 binary floating-point number using its decimal representation. + /// + /// The value to convert. + /// The underlying type of the value. + /// Returns a containing the unscaled value and scale. + private static NumberInfo ConvertFromDecimal(T value) where T : IBinaryFloatingPointIeee754 + { + const char zero = '0'; + const string format = "R"; + const string delimiter = "E"; + const StringComparison comparison = StringComparison.CurrentCultureIgnoreCase; + + int exponent = int.Parse(value.ToString("E", NumberFormatInfo.CurrentInfo).SubstringAfterLast(delimiter, comparison: comparison)); + + string digits = value + .ToString(format, NumberFormatInfo.CurrentInfo) + .SubstringBeforeFirst(delimiter, comparison: comparison) + .Where(char.IsDigit) + .JoinToString(string.Empty) + .PadRight(int.Max(0, exponent + 1), zero); + + BigInteger unscaledValue = BigInteger.Parse(digits) * T.Sign(value); + int scale = BigInteger.Abs(unscaledValue).ToString().Length - (exponent + 1); + + return new NumberInfo(unscaledValue, scale); + } + + /// + /// Determines whether the specified IEEE 754 binary floating-point number is zero or one. + /// + /// The value to check. + /// The result if the number is zero or one. + /// The underlying type of the value. + /// Returns true if the specified IEEE 754 binary floating-point number is zero or one; otherwise, false. + private static bool IsZeroOrOne(T value, out NumberInfo result) where T : IBinaryFloatingPointIeee754 + { + if (value == T.Zero || value == T.NegativeZero) + { + result = NumberInfo.Zero; + return true; + } + + if (value == T.One) + { + result = NumberInfo.One; + return true; + } + + if (value == T.NegativeOne) + { + result = NumberInfo.NegativeOne; + return true; + } + + result = default; + return false; + } + + /// + /// Requires that the specified value is a real number. + /// + /// The value to check. + /// The underlying type of the <see cref="IBinaryFloatingPointIeee754{TSelf}"/> value. + private static void RequireRealNumber(T value) where T : IBinaryFloatingPointIeee754 + { + Require(!T.IsNaN(value), "Value must not be NaN.", nameof(value)); + Require(!T.IsInfinity(value), "Value must not be infinite.", nameof(value)); + } +} diff --git a/OnixLabs.Core/Units/Temperature.Comparable.cs b/OnixLabs.Numerics/NumberInfo.Comparable.cs similarity index 62% rename from OnixLabs.Core/Units/Temperature.Comparable.cs rename to OnixLabs.Numerics/NumberInfo.Comparable.cs index 6ac6d87..6a427da 100644 --- a/OnixLabs.Core/Units/Temperature.Comparable.cs +++ b/OnixLabs.Numerics/NumberInfo.Comparable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -13,21 +13,22 @@ // limitations under the License. using System; +using System.Numerics; -namespace OnixLabs.Core.Units; +namespace OnixLabs.Numerics; -public readonly partial struct Temperature : IComparable>, IComparable +public readonly partial struct NumberInfo : IComparable, IComparable, IComparisonOperators { /// - /// Compares two values and returns an integer that indicates - /// whether the left-hand value is less than, equal to, or greater than the right-hand value. + /// Compares two values and returns an integer that indicates + /// whether the left-hand value is less than, equal to, or greater than the right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. /// Returns a value that indicates the relative order of the objects being compared. - public static int Compare(Temperature left, Temperature right) + public static int Compare(NumberInfo left, NumberInfo right) { - return left.Kelvin.CompareTo(right.Kelvin); + return NumberInfoOrdinalityComparer.Default.Compare(left, right); } /// @@ -37,7 +38,7 @@ public static int Compare(Temperature left, Temperature right) /// /// An object to compare with this instance. /// Returns a value that indicates the relative order of the objects being compared. - public int CompareTo(Temperature other) + public int CompareTo(NumberInfo other) { return Compare(this, other); } @@ -51,50 +52,50 @@ public int CompareTo(Temperature other) /// Returns a value that indicates the relative order of the objects being compared. public int CompareTo(object? obj) { - return this.CompareObject(obj); + return NumberInfoOrdinalityComparer.Default.Compare(this, obj); } /// - /// Performs a greater than comparison check between two values. + /// Determines whether the left-hand value is greater than the right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is greater than right-hand operand; otherwise, false. - public static bool operator >(Temperature left, Temperature right) + /// Returns True if the left-hand operand is greater than right-hand operand; otherwise, false. + public static bool operator >(NumberInfo left, NumberInfo right) { - return Compare(left, right) is 1; + return NumberInfoOrdinalityComparer.Default.IsGreaterThan(left, right); } /// - /// Performs a greater than or equal comparison check between two values. + /// Determines whether the left-hand value is greater than or equal to the right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is greater than or equal to right-hand operand; otherwise, false. - public static bool operator >=(Temperature left, Temperature right) + /// Returns true if the left-hand operand is greater than or equal to the right-hand operand; otherwise, false. + public static bool operator >=(NumberInfo left, NumberInfo right) { - return Compare(left, right) is 1 or 0; + return NumberInfoOrdinalityComparer.Default.IsGreaterThanOrEqual(left, right); } /// - /// Performs a less than comparison check between two values. + /// Determines whether the left-hand value is less than right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is less than right-hand operand; otherwise, false. - public static bool operator <(Temperature left, Temperature right) + /// Returns true if the left-hand operand is less than the right-hand operand; otherwise, false. + public static bool operator <(NumberInfo left, NumberInfo right) { - return Compare(left, right) is -1; + return NumberInfoOrdinalityComparer.Default.IsLessThan(left, right); } /// - /// Performs a less than or equal comparison check between two values. + /// Determines whether the left-hand value is less than or equal to the right-hand value. /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is less than or equal to right-hand operand; otherwise, false. - public static bool operator <=(Temperature left, Temperature right) + /// Returns true if the left-hand operand is less than or equal to the right-hand operand; otherwise, false. + public static bool operator <=(NumberInfo left, NumberInfo right) { - return Compare(left, right) is -1 or 0; + return NumberInfoOrdinalityComparer.Default.IsLessThanOrEqual(left, right); } } diff --git a/OnixLabs.Numerics/NumberInfo.Constants.cs b/OnixLabs.Numerics/NumberInfo.Constants.cs new file mode 100644 index 0000000..324c2d3 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfo.Constants.cs @@ -0,0 +1,50 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Globalization; + +namespace OnixLabs.Numerics; + +public readonly partial struct NumberInfo +{ + /// + /// Gets a instance representing zero. + /// + public static NumberInfo Zero => new(0, 0); + + /// + /// Gets a instance representing one. + /// + public static NumberInfo One => new(1, 0); + + /// + /// Gets a instance representing negative one. + /// + public static NumberInfo NegativeOne => new(-1, 0); + + /// + /// Gets the default number format. + /// + private const string DefaultNumberFormat = "G"; + + /// + /// Gets the default number styles for parsing decimal values. + /// + private const NumberStyles DefaultNumberStyles = NumberStyles.Any; + + /// + /// Gets the default culture for formatting and parsing operations. + /// + private static readonly CultureInfo DefaultCulture = CultureInfo.CurrentCulture; +} diff --git a/OnixLabs.Numerics/NumberInfo.Equatable.cs b/OnixLabs.Numerics/NumberInfo.Equatable.cs new file mode 100644 index 0000000..08f28ae --- /dev/null +++ b/OnixLabs.Numerics/NumberInfo.Equatable.cs @@ -0,0 +1,122 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Numerics; + +public readonly partial struct NumberInfo : IEquatable +{ + /// + /// Compares two instances of to determine whether their values are equal. + /// This method implements the comparer. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool Equals(NumberInfo left, NumberInfo right) + { + return Equals(left, right, NumberInfoEqualityComparer.Strict); + } + + /// + /// Compares two instances of to determine whether their values are equal. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// The equality comparer to use to determine equality. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool Equals(NumberInfo left, NumberInfo right, NumberInfoEqualityComparer comparer) + { + return comparer.Equals(left, right); + } + + /// + /// Compares the current instance of with the specified other instance of . + /// This method implements the comparer. + /// + /// The other instance of to compare with the current instance. + /// Returns true if the current instance is equal to the specified other instance; otherwise, false. + public bool Equals(NumberInfo other) + { + return Equals(this, other); + } + + /// + /// Compares the current instance of with the specified other instance of . + /// + /// The other instance of to compare with the current instance. + /// The equality comparer to use to determine equality. + /// Returns true if the current instance is equal to the specified other instance; otherwise, false. + public bool Equals(NumberInfo other, NumberInfoEqualityComparer comparer) + { + return Equals(this, other, comparer); + } + + /// + /// Checks for equality between this instance and another object. + /// This method implements the comparer. + /// + /// The object to check for equality. + /// Returns true if the object is equal to this instance; otherwise, false. + public override bool Equals(object? obj) + { + return obj is NumberInfo other && Equals(other); + } + + /// + /// Checks for equality between this instance and another object. + /// + /// The object to check for equality. + /// The equality comparer to use to determine equality. + /// Returns true if the object is equal to this instance; otherwise, false. + public bool Equals(object? obj, NumberInfoEqualityComparer comparer) + { + return obj is NumberInfo other && Equals(other, comparer); + } + + /// + /// Serves as a hash code function for this instance. + /// This method implements the comparer. + /// + /// A hash code for this instance. + public override int GetHashCode() + { + return NumberInfoEqualityComparer.Strict.GetHashCode(this); + } + + /// + /// Compares two instances of to determine whether their values are equal. + /// This method implements the comparer. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the two specified instances are equal; otherwise, false. + public static bool operator ==(NumberInfo left, NumberInfo right) + { + return Equals(left, right, NumberInfoEqualityComparer.Semantic); + } + + /// + /// Compares two instances of to determine whether their values are not equal. + /// This method implements the comparer. + /// + /// The left-hand value to compare. + /// The right-hand value to compare. + /// Returns true if the two specified instances are not equal; otherwise, false. + public static bool operator !=(NumberInfo left, NumberInfo right) + { + return Equals(left, right, NumberInfoEqualityComparer.Semantic); + } +} diff --git a/OnixLabs.Numerics/NumberInfo.Parse.cs b/OnixLabs.Numerics/NumberInfo.Parse.cs new file mode 100644 index 0000000..6827a73 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfo.Parse.cs @@ -0,0 +1,161 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; + +namespace OnixLabs.Numerics; + +public readonly partial struct NumberInfo : ISpanParsable +{ + /// + /// Parses the specified value into a value. + /// + /// The value to parse. + /// An object that provides culture-specific information about the specified value. + /// Returns a new instance parsed from the specified value. + public static NumberInfo Parse(string value, IFormatProvider? provider = null) + { + return Parse(value.AsSpan(), provider); + } + + /// + /// Parses the specified value into a value. + /// + /// The value to parse. + /// A bitwise combination of number styles that can be present in the specified value. + /// An object that provides culture-specific information about the specified value. + /// Returns a new instance parsed from the specified value. + public static NumberInfo Parse(string value, NumberStyles style, IFormatProvider? provider = null) + { + return Parse(value.AsSpan(), style, provider); + } + + /// + /// Parses the specified value into a value. + /// + /// The value to parse. + /// An object that provides culture-specific information about the specified value. + /// Returns a new instance parsed from the specified value. + public static NumberInfo Parse(ReadOnlySpan value, IFormatProvider? provider = null) + { + return Parse(value, DefaultNumberStyles, provider); + } + + /// + /// Parses the specified value into a value. + /// + /// The value to parse. + /// A bitwise combination of number styles that can be present in the specified value. + /// An object that provides culture-specific information about the specified value. + /// Returns a new instance parsed from the specified value. + public static NumberInfo Parse(ReadOnlySpan value, NumberStyles style, IFormatProvider? provider = null) + { + CultureInfo info = provider as CultureInfo ?? DefaultCulture; + if (TryParse(value, style, info, out NumberInfo result)) return result; + throw new FormatException($"The input string '{value}' was not in a correct format."); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, out NumberInfo result) + { + return TryParse(value.AsSpan(), out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// An object that provides culture-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, IFormatProvider? provider, out NumberInfo result) + { + return TryParse(value.AsSpan(), provider, out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// A bitwise combination of number styles that can be present in the specified value. + /// An object that provides culture-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, NumberStyles style, IFormatProvider? provider, out NumberInfo result) + { + return TryParse(value.AsSpan(), style, provider, out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, out NumberInfo result) + { + return TryParse(value, DefaultCulture, out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// An object that provides culture-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out NumberInfo result) + { + return TryParse(value, DefaultNumberStyles, provider, out result); + } + + /// + /// Tries to parse the specified value into a value. + /// + /// The value to parse. + /// A bitwise combination of number styles that can be present in the specified value. + /// An object that provides culture-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, NumberStyles style, IFormatProvider? provider, out NumberInfo result) + { + CultureInfo info = provider as CultureInfo ?? DefaultCulture; + NumberInfoParser parser = new(style, info); + return parser.TryParse(value, out result); + } +} diff --git a/OnixLabs.Numerics/NumberInfo.To.cs b/OnixLabs.Numerics/NumberInfo.To.cs new file mode 100644 index 0000000..43ff78d --- /dev/null +++ b/OnixLabs.Numerics/NumberInfo.To.cs @@ -0,0 +1,54 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; + +namespace OnixLabs.Numerics; + +public readonly partial struct NumberInfo : IFormattable +{ + /// + /// Formats the value of the current instance using the default format. + /// + /// The value of the current instance in the default format. + public override string ToString() + { + return ToString(DefaultNumberFormat, DefaultCulture); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(string? format, IFormatProvider? formatProvider = null) + { + return ToString((format ?? DefaultNumberFormat).AsSpan(), formatProvider); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + { + CultureInfo info = formatProvider as CultureInfo ?? DefaultCulture; + NumberInfoFormatter formatter = new(this, info, ['E', 'G']); + return formatter.Format(format); + } +} diff --git a/OnixLabs.Numerics/NumberInfo.cs b/OnixLabs.Numerics/NumberInfo.cs new file mode 100644 index 0000000..864174e --- /dev/null +++ b/OnixLabs.Numerics/NumberInfo.cs @@ -0,0 +1,109 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Numerics; + +/// +/// Represents component information about rational numbers. +/// +public readonly partial struct NumberInfo +{ + /// + /// Prevents a default instance of the struct from being created. + /// + /// The unscaled value of the represented number. + /// The scale of the represented number. + internal NumberInfo(BigInteger unscaledValue, int scale) + { + UnscaledValue = unscaledValue; + Scale = scale; + } + + /// + /// Gets the unscaled value of the represented number. + /// The unscaled value is represented as a signed value, including any trailing zeros. + /// If the represented number contains a fractional component, the trailing zeros are considered significant. + /// + public BigInteger UnscaledValue { get; } + + /// + /// Gets the scale of the represented number. + /// The scale is represented as a positive or neutral integer. + /// The scale indicates how many digits from the right-hand side of the represent the fractional component of the represented number. + /// + public int Scale { get; } + + /// + /// Gets the significand of the represented number. + /// The significand is represented as a signed value, excluding any trailing zeros. + /// If the represented number contains a fractional component, the trailing zeros are considered insignificant and must be calculated from the of the represented number. + /// + public BigInteger Significand + { + get + { + if (UnscaledValue == BigInteger.Zero) return BigInteger.Zero; + + BigInteger significand = UnscaledValue; + int exponent = 0; + + while (significand % BigInteger.Pow(10, exponent) == BigInteger.Zero) exponent++; + return significand / BigInteger.Pow(10, --exponent); + } + } + + /// + /// Gets the exponent of the represented number. + /// The exponent is represented as a positive, negative or neutral number. + /// + public int Exponent + { + get + { + if (UnscaledValue == BigInteger.Zero) return 0; + if (Scale == 0) return Precision - GenericMath.IntegerLength(Significand); + return -(Scale - (GenericMath.IntegerLength(UnscaledValue) - GenericMath.IntegerLength(Significand))); + } + } + + /// + /// Gets the precision of the represented number. + /// The precision is represented as a positive value, indicating how many significant digits the represented number contains. + /// If the represented number's or contain fewer digits that the , then trailing zeros are considered significant. + /// + public int Precision => int.Max(GenericMath.IntegerLength(UnscaledValue), Scale + 1); + + /// + /// Gets the sign of the represented number. + /// The sign is represented as negative one for negative numbers, positive one for positive numbers; otherwise, zero. + /// + public int Sign => UnscaledValue.Sign; + + /// + /// Gets the scale factor of the represented number. + /// + internal BigInteger ScaleFactor => BigInteger.Pow(10, Scale); + + /// + /// Gets the integral component of the represented number. + /// + internal BigInteger Integer => UnscaledValue / ScaleFactor; + + /// + /// Gets the fractional component of the represented number. + /// + internal BigInteger Fraction => BigInteger.Abs(UnscaledValue - Integer * ScaleFactor); +} diff --git a/OnixLabs.Numerics/NumberInfoEqualityComparer.cs b/OnixLabs.Numerics/NumberInfoEqualityComparer.cs new file mode 100644 index 0000000..7181e25 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoEqualityComparer.cs @@ -0,0 +1,118 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OnixLabs.Numerics; + +/// +/// Represents an equality comparer for comparing values. +/// +public abstract class NumberInfoEqualityComparer : IEqualityComparer, IEqualityComparer +{ + /// + /// Gets a that strictly compares values. + /// + public static readonly NumberInfoEqualityComparer Strict = new NumberInfoStrictEqualityComparer(); + + /// + /// Gets a that semantically compares values. + /// + public static readonly NumberInfoEqualityComparer Semantic = new NumberInfoSemanticEqualityComparer(); + + /// + /// Prevents a default instance of the class from being created. + /// + private NumberInfoEqualityComparer() + { + } + + /// Determines whether the specified values are equal. + /// The first object of type to compare. + /// The second object of type to compare. + /// Returns if the specified values are equal; otherwise, . + public abstract bool Equals(NumberInfo x, NumberInfo y); + + /// Returns a hash code for the specified value. + /// The value for which a hash code is to be returned. + /// Returns a hash code for the specified value. + public abstract int GetHashCode(NumberInfo obj); + + /// Determines whether the specified objects are equal. + /// The first object to compare. + /// The second object to compare. + /// Returns if the specified objects are both of type and are equal; otherwise, . + public new bool Equals(object? x, object? y) + { + return x is NumberInfo left && y is NumberInfo right && Equals(left, right); + } + + /// Returns a hash code for the specified object. + /// The for which a hash code is to be returned. + /// A hash code for the specified object. + public int GetHashCode(object obj) + { + return obj is NumberInfo value ? GetHashCode(value) : obj.GetHashCode(); + } + + /// + /// Represents an equality comparer that compares values using strict equality. + /// Strict equality is determined by comparing and properties. + /// + private sealed class NumberInfoStrictEqualityComparer : NumberInfoEqualityComparer + { + /// Determines whether the specified values are equal. + /// The first object of type to compare. + /// The second object of type to compare. + /// Returns if the specified values are equal; otherwise, . + public override bool Equals(NumberInfo x, NumberInfo y) + { + return x.UnscaledValue == y.UnscaledValue && x.Scale == y.Scale; + } + + /// Returns a hash code for the specified value. + /// The value for which a hash code is to be returned. + /// Returns a hash code for the specified value. + public override int GetHashCode(NumberInfo obj) + { + return HashCode.Combine(obj.UnscaledValue, obj.Scale); + } + } + + /// + /// Represents an equality comparer that compares values using semantic equality. + /// Semantic equality is determined by comparing and properties. + /// + private sealed class NumberInfoSemanticEqualityComparer : NumberInfoEqualityComparer + { + /// Determines whether the specified values are equal. + /// The first object of type to compare. + /// The second object of type to compare. + /// Returns if the specified values are equal; otherwise, . + public override bool Equals(NumberInfo x, NumberInfo y) + { + return NumberInfoOrdinalityComparer.Default.IsEqual(x, y); + } + + /// Returns a hash code for the specified value. + /// The value for which a hash code is to be returned. + /// Returns a hash code for the specified value. + public override int GetHashCode(NumberInfo obj) + { + return HashCode.Combine(obj.Significand, obj.Exponent); + } + } +} diff --git a/OnixLabs.Numerics/NumberInfoFormatter.FormatCurrency.cs b/OnixLabs.Numerics/NumberInfoFormatter.FormatCurrency.cs new file mode 100644 index 0000000..f159b14 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoFormatter.FormatCurrency.cs @@ -0,0 +1,119 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using OnixLabs.Core.Text; + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoFormatter +{ + /// + /// Formats the current value using the currency format. + /// + private void FormatCurrency() + { + FormatInteger(numberFormat.CurrencyGroupSizes, numberFormat.CurrencyGroupSeparator); + FormatFraction(numberFormat.CurrencyDecimalSeparator); + FormatCurrencyPositivePattern(); + FormatCurrencyNegativePattern(); + } + + /// + /// Applies currency positive pattern formatting to the current being formatted. + /// + private void FormatCurrencyPositivePattern() + { + if (BigInteger.IsNegative(value.UnscaledValue)) return; + + switch (numberFormat.CurrencyPositivePattern) + { + case 0: // $n + builder.Prepend(numberFormat.CurrencySymbol); + break; + case 1: // n$ + builder.Append(numberFormat.CurrencySymbol); + break; + case 2: // $ n + builder.Prepend(numberFormat.CurrencySymbol, Whitespace); + break; + case 3: // n $ + builder.Append(Whitespace, numberFormat.CurrencySymbol); + break; + } + } + + /// + /// Applies currency negative pattern formatting to the current being formatted. + /// + private void FormatCurrencyNegativePattern() + { + if (BigInteger.IsPositive(value.UnscaledValue)) return; + + switch (numberFormat.CurrencyNegativePattern) + { + case 0: // ($n) + builder.Prepend(numberFormat.CurrencySymbol).Wrap(LeadingParenthesis, TrailingParenthesis); + break; + case 1: // -$n + builder.Prepend(numberFormat.NegativeSign, numberFormat.CurrencySymbol); + break; + case 2: // $-n + builder.Prepend(numberFormat.CurrencySymbol, numberFormat.NegativeSign); + break; + case 3: // $n- + builder.Prepend(numberFormat.CurrencySymbol).Append(numberFormat.NegativeSign); + break; + case 4: // (n$) + builder.Append(numberFormat.CurrencySymbol).Wrap(LeadingParenthesis, TrailingParenthesis); + break; + case 5: // -n$ + builder.Prepend(numberFormat.NegativeSign).Append(numberFormat.CurrencySymbol); + break; + case 6: // n-$ + builder.Append(numberFormat.NegativeSign, numberFormat.CurrencySymbol); + break; + case 7: // n$- + builder.Append(numberFormat.CurrencySymbol, numberFormat.NegativeSign); + break; + case 8: // -n $ + builder.Prepend(numberFormat.NegativeSign).Append(Whitespace, numberFormat.CurrencySymbol); + break; + case 9: // -$ n + builder.Prepend(numberFormat.NegativeSign, numberFormat.CurrencySymbol, Whitespace); + break; + case 10: // n $- + builder.Append(Whitespace, numberFormat.CurrencySymbol, numberFormat.NegativeSign); + break; + case 11: // $ n- + builder.Prepend(numberFormat.CurrencySymbol, Whitespace).Append(numberFormat.NegativeSign); + break; + case 12: // $ -n + builder.Prepend(numberFormat.CurrencySymbol, Whitespace, numberFormat.NegativeSign); + break; + case 13: // n- $ + builder.Append(numberFormat.NegativeSign, Whitespace, numberFormat.CurrencySymbol); + break; + case 14: // ($ n) + builder.Prepend(numberFormat.CurrencySymbol, Whitespace).Wrap(LeadingParenthesis, TrailingParenthesis); + break; + case 15: // (n $) + builder.Append(Whitespace, numberFormat.CurrencySymbol).Wrap(LeadingParenthesis, TrailingParenthesis); + break; + case 16: // $- n + builder.Prepend(numberFormat.CurrencySymbol, numberFormat.NegativeSign, Whitespace); + break; + } + } +} diff --git a/OnixLabs.Numerics/NumberInfoFormatter.FormatDecimal.cs b/OnixLabs.Numerics/NumberInfoFormatter.FormatDecimal.cs new file mode 100644 index 0000000..e9fd2d4 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoFormatter.FormatDecimal.cs @@ -0,0 +1,28 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoFormatter +{ + /// + /// Formats the current value using the decimal format. + /// + private void FormatDecimal() + { + FormatInteger(numberFormat.NumberGroupSizes, numberFormat.NumberGroupSeparator); + FormatFraction(numberFormat.NumberDecimalSeparator); + FormatNumberNegativePattern(); + } +} diff --git a/OnixLabs.Numerics/NumberInfoFormatter.FormatExponential.cs b/OnixLabs.Numerics/NumberInfoFormatter.FormatExponential.cs new file mode 100644 index 0000000..50a2a90 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoFormatter.FormatExponential.cs @@ -0,0 +1,42 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using OnixLabs.Core.Text; + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoFormatter +{ + /// + /// Formats the current value using the exponential (otherwise known as scientific notation) format. + /// + /// The exponentiation specifier, which is either an uppercase E, or lowercase e. + private void FormatExponential(char specifier) + { + builder.Append(BigInteger.Abs(value.UnscaledValue)); + + if (value == NumberInfo.Zero) return; + + int exponent = builder.Length - value.Scale - 1; + builder.Trim('0').Insert(1, numberFormat.NumberDecimalSeparator).TrimEnd(numberFormat.NumberDecimalSeparator); + + if (exponent == 0) return; + + string sign = exponent > 0 ? numberFormat.PositiveSign : numberFormat.NegativeSign; + builder.Append(specifier, sign, int.Abs(exponent)); + + if (value.UnscaledValue < BigInteger.Zero) builder.Prepend(numberFormat.NegativeSign); + } +} diff --git a/OnixLabs.Core/Units/Temperature.Constants.cs b/OnixLabs.Numerics/NumberInfoFormatter.FormatFixed.cs similarity index 64% rename from OnixLabs.Core/Units/Temperature.Constants.cs rename to OnixLabs.Numerics/NumberInfoFormatter.FormatFixed.cs index fac061d..34b7747 100644 --- a/OnixLabs.Core/Units/Temperature.Constants.cs +++ b/OnixLabs.Numerics/NumberInfoFormatter.FormatFixed.cs @@ -1,28 +1,28 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -namespace OnixLabs.Core.Units; +namespace OnixLabs.Numerics; -public readonly partial struct Temperature +internal sealed partial class NumberInfoFormatter { /// - /// Represents an absolute zero (0°K) value. + /// Formats the current value using the fixed format. /// - public static Temperature Zero => default; - - /// - /// Gets the default format. - /// - private const string DefaultFormat = "K"; + private void FormatFixed() + { + FormatInteger([]); + FormatFraction(numberFormat.NumberDecimalSeparator); + FormatNumberNegativePattern(); + } } diff --git a/OnixLabs.Numerics/NumberInfoFormatter.FormatGeneral.cs b/OnixLabs.Numerics/NumberInfoFormatter.FormatGeneral.cs new file mode 100644 index 0000000..5d51bb3 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoFormatter.FormatGeneral.cs @@ -0,0 +1,28 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoFormatter +{ + /// + /// Formats the current value using the general format. + /// + private void FormatGeneral() + { + FormatInteger([]); + FormatFraction(numberFormat.NumberDecimalSeparator); + FormatNumberNegativePattern(); + } +} diff --git a/OnixLabs.Numerics/NumberInfoFormatter.FormatNumber.cs b/OnixLabs.Numerics/NumberInfoFormatter.FormatNumber.cs new file mode 100644 index 0000000..3932b54 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoFormatter.FormatNumber.cs @@ -0,0 +1,58 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using OnixLabs.Core.Text; + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoFormatter +{ + /// + /// Formats the current value using the number format. + /// + private void FormatNumber() + { + FormatInteger(numberFormat.NumberGroupSizes, numberFormat.NumberGroupSeparator); + FormatFraction(numberFormat.NumberDecimalSeparator); + FormatNumberNegativePattern(); + } + + /// + /// Applies number negative pattern formatting to the current being formatted. + /// + private void FormatNumberNegativePattern() + { + if (BigInteger.IsPositive(value.UnscaledValue)) return; + + switch (numberFormat.NumberNegativePattern) + { + case 0: // (n) + builder.Wrap(LeadingParenthesis, TrailingParenthesis); + break; + case 1: // -n + builder.Prepend(numberFormat.NegativeSign); + break; + case 2: // - n + builder.Prepend(numberFormat.NegativeSign, Whitespace); + break; + case 3: // n- + builder.Append(numberFormat.NegativeSign); + break; + case 4: // n - + builder.Append(Whitespace, numberFormat.NegativeSign); + break; + } + } +} diff --git a/OnixLabs.Numerics/NumberInfoFormatter.FormatPercentage.cs b/OnixLabs.Numerics/NumberInfoFormatter.FormatPercentage.cs new file mode 100644 index 0000000..ab85fdb --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoFormatter.FormatPercentage.cs @@ -0,0 +1,104 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; +using OnixLabs.Core.Text; + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoFormatter +{ + /// + /// Formats the current value using the percentage format. + /// + private void FormatPercent() + { + FormatInteger(numberFormat.PercentGroupSizes, numberFormat.PercentGroupSeparator); + FormatFraction(numberFormat.PercentDecimalSeparator); + FormatPercentPositivePattern(); + FormatPercentNegativePattern(); + } + + /// + /// Applies percent positive pattern formatting to the current being formatted. + /// + private void FormatPercentPositivePattern() + { + if (BigInteger.IsNegative(value.UnscaledValue)) return; + + switch (numberFormat.PercentPositivePattern) + { + case 0: // n % + builder.Append(Whitespace, numberFormat.PercentSymbol); + break; + case 1: // n% + builder.Append(numberFormat.PercentSymbol); + break; + case 2: // %n + builder.Prepend(numberFormat.PercentSymbol); + break; + case 3: // % n + builder.Prepend(numberFormat.PercentSymbol, Whitespace); + break; + } + } + + /// + /// Applies percent negative pattern formatting to the current being formatted. + /// + private void FormatPercentNegativePattern() + { + if (BigInteger.IsPositive(value.UnscaledValue)) return; + + switch (numberFormat.PercentNegativePattern) + { + case 0: // -n % + builder.Prepend(numberFormat.NegativeSign).Append(Whitespace, numberFormat.PercentSymbol); + break; + case 1: // -n% + builder.Prepend(numberFormat.NegativeSign).Append(numberFormat.PercentSymbol); + break; + case 2: // -%n + builder.Prepend(numberFormat.NegativeSign, numberFormat.PercentSymbol); + break; + case 3: // %-n + builder.Prepend(numberFormat.PercentSymbol, numberFormat.NegativeSign); + break; + case 4: // %n- + builder.Prepend(numberFormat.PercentSymbol).Append(numberFormat.NegativeSign); + break; + case 5: // n-% + builder.Append(numberFormat.NegativeSign, numberFormat.PercentSymbol); + break; + case 6: // n%- + builder.Append(numberFormat.PercentSymbol, numberFormat.NegativeSign); + break; + case 7: // -% n + builder.Prepend(numberFormat.NegativeSign, numberFormat.PercentSymbol, Whitespace); + break; + case 8: // n %- + builder.Append(Whitespace, numberFormat.PercentSymbol, numberFormat.NegativeSign); + break; + case 9: // % n- + builder.Prepend(numberFormat.PercentSymbol, Whitespace).Append(numberFormat.NegativeSign); + break; + case 10: // % -n + builder.Prepend(numberFormat.PercentSymbol, Whitespace, numberFormat.NegativeSign); + break; + case 11: // n- % + builder.Append(numberFormat.NegativeSign, Whitespace, numberFormat.PercentSymbol); + break; + } + } +} diff --git a/OnixLabs.Numerics/NumberInfoFormatter.cs b/OnixLabs.Numerics/NumberInfoFormatter.cs new file mode 100644 index 0000000..d32b864 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoFormatter.cs @@ -0,0 +1,124 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Numerics; +using System.Text; +using OnixLabs.Core.Text; + +namespace OnixLabs.Numerics; + +/// +/// Represents a formatter for formatting values. +/// +/// The value to format. +/// The format provider, which should be a containing the desired format details. +/// Specifies which formats are allowed for formatting. +internal sealed partial class NumberInfoFormatter(NumberInfo value, IFormatProvider formatProvider, IEnumerable allowedFormats) +{ + internal const char DefaultFormat = 'G'; + + private const char LeadingParenthesis = '('; + private const char TrailingParenthesis = ')'; + private const char Whitespace = ' '; + + private readonly StringBuilder builder = new(); + private readonly NumberFormatInfo numberFormat = NumberFormatInfo.GetInstance(formatProvider); + private readonly IEnumerable allowedFormats = allowedFormats.Select(char.ToUpperInvariant); + + /// + /// Formats the current value using the specified format. + /// + /// The desired format of the value. + /// Returns a representation of the current value. + public string Format(ReadOnlySpan format) + { + char specifier = format.IsEmpty || format.IsWhiteSpace() ? DefaultFormat : format[0]; + char specifierUpperInvariant = char.ToUpperInvariant(specifier); + + if (!allowedFormats.Contains(specifierUpperInvariant)) return format.ToString(); + + switch (specifierUpperInvariant) + { + case 'C': + FormatCurrency(); + break; + case 'D': + FormatDecimal(); + break; + case 'E': + FormatExponential(specifier); + break; + case 'F': + FormatFixed(); + break; + case 'G': + FormatGeneral(); + break; + case 'N': + FormatNumber(); + break; + case 'P': + FormatPercent(); + break; + default: + return format.ToString(); + } + + return builder.ToString(); + } + + /// + /// Formats the integral component of the current value. + /// + /// The sizes of each number group. + /// The separator that separates each number group. + private void FormatInteger(IReadOnlyList grouping, string separator = "") + { + builder.Append(BigInteger.Abs(value.Integer)); + + if (grouping.Count == 0) return; + + int position = builder.Length - 1; + int count = 0; + int index = 0; + + while (position > 0) + { + if (char.IsDigit(builder[position])) count++; + + if (count == grouping[index]) + { + builder.Insert(position, separator); + count = 0; + + if (index < grouping.Count - 1) index++; + } + + position--; + } + } + + /// + /// Formats the fractional component of the current value. + /// + /// The separator that separates the integral and fractional components. + private void FormatFraction(string separator) + { + if (value.Scale > 0) builder.Append(separator, value.Fraction.ToString().PadLeft(value.Scale, '0')); + } +} diff --git a/OnixLabs.Numerics/NumberInfoOrdinalityComparer.cs b/OnixLabs.Numerics/NumberInfoOrdinalityComparer.cs new file mode 100644 index 0000000..a31b6e9 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoOrdinalityComparer.cs @@ -0,0 +1,119 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Numerics; + +namespace OnixLabs.Numerics; + +/// +/// Represents an ordinality comparer for comparing values. +/// +public sealed class NumberInfoOrdinalityComparer : IComparer, IComparer +{ + /// + /// Gets the default ordinal comparer for comparing values. + /// + public static readonly NumberInfoOrdinalityComparer Default = new(); + + /// + /// Prevents a default instance of the class from being created. + /// + private NumberInfoOrdinalityComparer() + { + } + + /// Compares two values and returns a value indicating whether one is less than, equal to, or greater than the other. + /// The first value to compare. + /// The second value to compare. + /// Returns a signed integer that indicates the relative order of the values being compared. + public int Compare(NumberInfo x, NumberInfo y) + { + BigInteger factor = BigInteger.Min(x.ScaleFactor, y.ScaleFactor); + BigInteger xNormalized = x.UnscaledValue * y.ScaleFactor / factor; + BigInteger yNormalized = y.UnscaledValue * x.ScaleFactor / factor; + + return xNormalized.CompareTo(yNormalized); + } + + /// Compares two values and returns a value indicating whether one is less than, equal to, or greater than the other. + /// The first value to compare. + /// The second value to compare. + /// Returns a signed integer that indicates the relative order of the values being compared. + /// If either or are not of type . + public int Compare(object? x, object? y) + { + if (x is not NumberInfo xInfo) throw new ArgumentException($"Argument must be of type {nameof(NumberInfo)}", nameof(x)); + if (y is not NumberInfo yInfo) throw new ArgumentException($"Argument must be of type {nameof(NumberInfo)}", nameof(y)); + + return Compare(xInfo, yInfo); + } + + /// + /// Determines whether the left-hand value is equal to the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is equal to the right-hand value; otherwise, . + public bool IsEqual(NumberInfo left, NumberInfo right) + { + return Compare(left, right) is 0; + } + + /// + /// Determines whether the left-hand value is greater than the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is greater than the right-hand value; otherwise, . + public bool IsGreaterThan(NumberInfo left, NumberInfo right) + { + return Compare(left, right) is 1; + } + + /// + /// Determines whether the left-hand value is greater than, or equal to the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is greater than, or equal to the right-hand value; otherwise, . + public bool IsGreaterThanOrEqual(NumberInfo left, NumberInfo right) + { + return Compare(left, right) is 0 or 1; + } + + /// + /// Determines whether the left-hand value is less than the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is less than the right-hand value; otherwise, . + public bool IsLessThan(NumberInfo left, NumberInfo right) + { + return Compare(left, right) is -1; + } + + /// + /// Determines whether the left-hand value is less than, or equal to the right-hand value. + /// + /// The left-hand value to compare. + /// The left-hand value to compare. + /// Returns if the left-hand value is less than, or equal to the right-hand value; otherwise, . + public bool IsLessThanOrEqual(NumberInfo left, NumberInfo right) + { + return Compare(left, right) is -1 or 0; + } +} diff --git a/OnixLabs.Numerics/NumberInfoParser.Sanitize.cs b/OnixLabs.Numerics/NumberInfoParser.Sanitize.cs new file mode 100644 index 0000000..2bc0c66 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoParser.Sanitize.cs @@ -0,0 +1,142 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using static System.Globalization.NumberStyles; + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoParser +{ + private bool TryTrimLeadingWhitespace(ref ReadOnlySpan value) + { + ReadOnlySpan result = value.TrimStart(); + + if (result.SequenceEqual(value)) return true; + if (!style.HasFlag(AllowLeadingWhite)) return false; + + value = result; + return true; + } + + private bool TryTrimTrailingWhitespace(ref ReadOnlySpan value) + { + ReadOnlySpan result = value.TrimEnd(); + + if (result.SequenceEqual(value)) return true; + if (!style.HasFlag(AllowTrailingWhite)) return false; + + value = result; + return true; + } + + private bool TryTrimLeadingCurrencySymbol(ref ReadOnlySpan value) + { + ReadOnlySpan result = value.TrimStart(numberFormat.CurrencySymbol); + + if (result.SequenceEqual(value)) return true; + if (!style.HasFlag(AllowCurrencySymbol)) return false; + + value = result; + return true; + } + + private bool TryTrimTrailingCurrencySymbol(ref ReadOnlySpan value) + { + ReadOnlySpan result = value.TrimEnd(numberFormat.CurrencySymbol); + + if (result.SequenceEqual(value)) return true; + if (!style.HasFlag(AllowCurrencySymbol)) return false; + + value = result; + return true; + } + + private bool TryTrimLeadingPositiveSign(ref ReadOnlySpan value, out bool hasLeadingPositiveSign) + { + hasLeadingPositiveSign = value.StartsWith(numberFormat.PositiveSign, Comparison); + + if (!hasLeadingPositiveSign) return true; + if (!style.HasFlag(AllowLeadingSign)) return false; + + value = value.TrimStart(numberFormat.PositiveSign); + return true; + } + + private bool TryTrimTrailingPositiveSign(ref ReadOnlySpan value, out bool hasTrailingPositiveSign) + { + hasTrailingPositiveSign = value.EndsWith(numberFormat.PositiveSign, Comparison); + + if (!hasTrailingPositiveSign) return true; + if (!style.HasFlag(AllowTrailingSign)) return false; + + value = value.TrimStart(numberFormat.PositiveSign); + return true; + } + + private bool TryTrimLeadingNegativeSign(ref ReadOnlySpan value, out bool hasLeadingNegativeSign) + { + hasLeadingNegativeSign = value.StartsWith(numberFormat.NegativeSign, Comparison); + + if (!hasLeadingNegativeSign) return true; + if (!style.HasFlag(AllowLeadingSign)) return false; + + value = value.TrimStart(numberFormat.NegativeSign); + return true; + } + + private bool TryTrimTrailingNegativeSign(ref ReadOnlySpan value, out bool hasTrailingNegativeSign) + { + hasTrailingNegativeSign = value.EndsWith(numberFormat.NegativeSign, Comparison); + + if (!hasTrailingNegativeSign) return true; + if (!style.HasFlag(AllowTrailingSign)) return false; + + value = value.TrimStart(numberFormat.NegativeSign); + return true; + } + + private bool TryTrimParentheses(ref ReadOnlySpan value, out bool hasParentheses) + { + hasParentheses = false; + bool hasLeadingParenthesis = value.StartsWith(LeadingParenthesis, Comparison); + bool hasTrailingParenthesis = value.EndsWith(TrailingParenthesis, Comparison); + bool areParenthesesAllowed = style.HasFlag(AllowParentheses); + + if (hasLeadingParenthesis && hasTrailingParenthesis && areParenthesesAllowed) + { + hasParentheses = true; + value = value.TrimStart(LeadingParenthesis).TrimEnd(TrailingParenthesis); + return true; + } + + return !hasLeadingParenthesis && !hasTrailingParenthesis; + } + + private bool TryTrimExponent(ref ReadOnlySpan value, out int exponent) + { + exponent = default; + + int index = value.IndexOf(ExponentSymbol, Comparison); + int lastIndex = value.LastIndexOf(ExponentSymbol, Comparison); + + if (index == -1) return true; + if (index != lastIndex) return false; + + ReadOnlySpan chars = value[(index + 1)..]; + value = value[..index]; + + return int.TryParse(chars, culture, out exponent) && style.HasFlag(AllowExponent); + } +} diff --git a/OnixLabs.Numerics/NumberInfoParser.SanitizeCurrency.cs b/OnixLabs.Numerics/NumberInfoParser.SanitizeCurrency.cs new file mode 100644 index 0000000..930cb4c --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoParser.SanitizeCurrency.cs @@ -0,0 +1,138 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Linq; + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoParser +{ + private bool TrySanitizeCurrency(ref ReadOnlySpan value, out int sign) + { + sign = 1; + + bool hasParentheses = false; + bool hasLeadingNegativeSign = false; + bool hasTrailingNegativeSign = false; + + if (!TryTrimLeadingWhitespace(ref value)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + + switch (numberFormat.CurrencyPositivePattern) + { + case 0: // $n + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + break; + case 1: // n$ + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + break; + case 2: // $ n + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + if (!TryTrimLeadingWhitespace(ref value)) return false; + break; + case 3: // n $ + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + break; + } + + switch (numberFormat.CurrencyNegativePattern) + { + case 0: // ($n) + if (!TryTrimParentheses(ref value, out hasParentheses)) return false; + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + break; + case 1: // -$n + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + break; + case 2: // $-n + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + break; + case 3: // $n- + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + if (!TryTrimTrailingNegativeSign(ref value, out hasTrailingNegativeSign)) return false; + break; + case 4: // (n$) + if (!TryTrimParentheses(ref value, out hasParentheses)) return false; + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + break; + case 5: // -n$ + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + break; + case 6: // n-$ + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + if (!TryTrimTrailingNegativeSign(ref value, out hasTrailingNegativeSign)) return false; + break; + case 7: // n$- + if (!TryTrimTrailingNegativeSign(ref value, out hasTrailingNegativeSign)) return false; + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + break; + case 8: // -n $ + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + break; + case 9: // -$ n + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + if (!TryTrimLeadingWhitespace(ref value)) return false; + break; + case 10: // n $- + if (!TryTrimTrailingNegativeSign(ref value, out hasTrailingNegativeSign)) return false; + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + break; + case 11: // $ n- + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + if (!TryTrimLeadingWhitespace(ref value)) return false; + if (!TryTrimTrailingNegativeSign(ref value, out hasTrailingNegativeSign)) return false; + break; + case 12: // $ -n + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + if (!TryTrimLeadingWhitespace(ref value)) return false; + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + break; + case 13: // n- $ + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + if (!TryTrimTrailingNegativeSign(ref value, out hasTrailingNegativeSign)) return false; + break; + case 14: // ($ n) + if (!TryTrimParentheses(ref value, out hasParentheses)) return false; + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + if (!TryTrimLeadingWhitespace(ref value)) return false; + break; + case 15: // (n $) + if (!TryTrimParentheses(ref value, out hasParentheses)) return false; + if (!TryTrimTrailingCurrencySymbol(ref value)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + break; + case 16: // $- n + if (!TryTrimLeadingCurrencySymbol(ref value)) return false; + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + if (!TryTrimLeadingWhitespace(ref value)) return false; + break; + } + + bool[] values = [hasParentheses, hasLeadingNegativeSign, hasTrailingNegativeSign]; + if (values.Count(value => value) > 1) return false; + + if (hasParentheses || hasLeadingNegativeSign || hasTrailingNegativeSign) sign = -1; + return true; + } +} diff --git a/OnixLabs.Numerics/NumberInfoParser.SanitizeNumber.cs b/OnixLabs.Numerics/NumberInfoParser.SanitizeNumber.cs new file mode 100644 index 0000000..55ca83a --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoParser.SanitizeNumber.cs @@ -0,0 +1,76 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Linq; + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoParser +{ + private bool TrySanitizeNumber(ref ReadOnlySpan value, out int sign, out int exponent) + { + sign = 1; + exponent = 0; + + bool hasParentheses = false; + bool hasLeadingPositiveSign = false; + bool hasLeadingNegativeSign = false; + bool hasTrailingPositiveSign = false; + bool hasTrailingNegativeSign = false; + + // Trim overall leading and trailing whitespace + if (!TryTrimLeadingWhitespace(ref value)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + + if (!TryTrimLeadingPositiveSign(ref value, out hasLeadingPositiveSign)) return false; + if (!TryTrimTrailingPositiveSign(ref value, out hasTrailingPositiveSign)) return false; + + switch (numberFormat.NumberNegativePattern) + { + case 0: // (n) + if (!TryTrimParentheses(ref value, out hasParentheses)) return false; + break; + case 1: // -n + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + break; + case 2: // - n + if (!TryTrimLeadingNegativeSign(ref value, out hasLeadingNegativeSign)) return false; + if (!TryTrimLeadingWhitespace(ref value)) return false; + break; + case 3: // n- + if (!TryTrimTrailingNegativeSign(ref value, out hasTrailingNegativeSign)) return false; + break; + case 4: + if (!TryTrimTrailingNegativeSign(ref value, out hasTrailingNegativeSign)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + break; + } + + // Trim whitespace that appears after a leading positive or negative sign + if (!TryTrimLeadingWhitespace(ref value)) return false; + if (!TryTrimTrailingWhitespace(ref value)) return false; + + if (!TryTrimExponent(ref value, out exponent)) return false; + + // Trim whitespace that appears between the number and an exponent + if (!TryTrimTrailingWhitespace(ref value)) return false; + + bool[] values = [hasParentheses, hasLeadingPositiveSign, hasLeadingNegativeSign, hasTrailingPositiveSign, hasTrailingNegativeSign]; + if (values.Count(value => value) > 1) return false; + + if (hasParentheses || hasLeadingNegativeSign || hasTrailingNegativeSign) sign = -1; + return true; + } +} diff --git a/OnixLabs.Numerics/NumberInfoParser.cs b/OnixLabs.Numerics/NumberInfoParser.cs new file mode 100644 index 0000000..54a8094 --- /dev/null +++ b/OnixLabs.Numerics/NumberInfoParser.cs @@ -0,0 +1,119 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Globalization; +using System.Numerics; +using static System.Globalization.NumberStyles; + +namespace OnixLabs.Numerics; + +internal sealed partial class NumberInfoParser(NumberStyles style, IFormatProvider culture) +{ + private const string LeadingParenthesis = "("; + private const string TrailingParenthesis = ")"; + private const string ExponentSymbol = "e"; + private const StringComparison Comparison = StringComparison.InvariantCultureIgnoreCase; + + private readonly NumberFormatInfo numberFormat = NumberFormatInfo.GetInstance(culture); + + public bool TryParse(ReadOnlySpan value, out NumberInfo result) + { + result = default; + + int sign = 1; + int exponent = 0; + + // Disallow the following number styles as they are unsupported. + if (style == None) return false; + if (style.HasFlag(AllowHexSpecifier)) return false; + if (style.HasFlag(AllowBinarySpecifier)) return false; + + // Special handling for sanitization of currency values. + if (style == Currency) + { + if (!TrySanitizeCurrency(ref value, out sign)) return false; + } + else + { + if (!TrySanitizeNumber(ref value, out sign, out exponent)) return false; + } + + // At this point, only digits, thousand and decimal separators should remain. + if (!TryGetNumberInfo(ref value, out NumberInfo rawResult)) return false; + + result = new NumberInfo(rawResult.UnscaledValue * sign, int.Max(rawResult.Scale - exponent, 0)); + return true; + } + + private bool TryGetNumberInfo(ref ReadOnlySpan value, out NumberInfo result) + { + result = default; + + BigInteger unscaledValue = BigInteger.Zero; + int scale = 0; + bool hasDecimalPoint = false; + + while (value.Length > 0) + { + if (char.IsAsciiDigit(value[0])) + { + int digit = value[0] - '0'; + unscaledValue *= 10; + unscaledValue += digit; + + if (hasDecimalPoint) scale++; + + value = value[1..]; + continue; + } + + if (value.StartsWith(numberFormat.NumberGroupSeparator)) + { + if (!style.HasFlag(AllowThousands)) return false; + value = value.TrimStart(numberFormat.NumberGroupSeparator); + continue; + } + + if (value.StartsWith(numberFormat.CurrencyGroupSeparator)) + { + if (!style.HasFlag(AllowThousands)) return false; + value = value.TrimStart(numberFormat.CurrencyGroupSeparator); + continue; + } + + if (value.StartsWith(numberFormat.NumberDecimalSeparator)) + { + if (hasDecimalPoint || !style.HasFlag(AllowDecimalPoint)) return false; + hasDecimalPoint = true; + value = value.TrimStart(numberFormat.NumberDecimalSeparator); + continue; + } + + if (value.StartsWith(numberFormat.CurrencyDecimalSeparator)) + { + if (hasDecimalPoint || !style.HasFlag(AllowDecimalPoint)) return false; + hasDecimalPoint = true; + value = value.TrimStart(numberFormat.CurrencyDecimalSeparator); + continue; + } + + // If we reach this point, the start of the string isn't an ascii digit, thousand or decimal separator, therefore false. + return false; + } + + result = new NumberInfo(unscaledValue, scale); + return true; + } +} diff --git a/OnixLabs.Numerics/NumericsExtensions.cs b/OnixLabs.Numerics/NumericsExtensions.cs new file mode 100644 index 0000000..217620b --- /dev/null +++ b/OnixLabs.Numerics/NumericsExtensions.cs @@ -0,0 +1,212 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.ComponentModel; +using System.Numerics; + +namespace OnixLabs.Numerics; + +/// +/// Provides extension methods for numeric types. +/// +[EditorBrowsable(EditorBrowsableState.Never)] +public static class NumericsExtensions +{ + /// + /// Gets the minimum value of a as a . + /// + private static readonly BigInteger MinDecimal = new(decimal.MinValue); + + /// + /// Gets the maximum value of a as a . + /// + private static readonly BigInteger MaxDecimal = new(decimal.MaxValue); + + /// + /// Gets the unscaled value of the current . + /// + /// The from which to obtain an unscaled value. + /// Returns the unscaled value of the current as a . + public static BigInteger GetUnscaledValue(this decimal value) + { + const int significandSize = 13; + int[] significandBits = decimal.GetBits(value); + byte[] significandBytes = new byte[significandSize]; + Buffer.BlockCopy(significandBits, 0, significandBytes, 0, significandSize); + BigInteger result = new(significandBytes); + + return decimal.IsPositive(value) ? result : -result; + } + + /// + /// Gets the current value as an unscaled integer. + /// + /// The value to get as an unscaled integer. + /// The desired scale of the result. + /// The scale mode of the desired result. + /// The underlying type. + /// Returns an unscaled integer representation of the current value. + private static BigInteger GetUnscaledInteger(this T value, int scale, ScaleMode mode) where T : IBinaryInteger + { + Require(scale >= 0, "Scale must be greater than or equal to zero.", nameof(value)); + RequireIsDefined(mode, nameof(mode)); + + BigInteger integer = value.ToBigInteger(); + return scale == 0 || mode == ScaleMode.Fractional ? integer : integer * BigInteger.Pow(10, scale); + } + + /// + /// Determines whether the current value is inclusively between the specified minimum and maximum values. + /// + /// The value to check. + /// The inclusive minimum value. + /// The inclusive maximum value. + /// The underlying type. + /// Returns true if the current value is inclusively between the specified minimum and maximum values; otherwise false. + public static bool IsBetween(this T value, T minimum, T maximum) where T : INumber + { + return value >= minimum && value <= maximum; + } + + /// + /// Converts the current value to a value. + /// + /// The value to convert. + /// The scale of the value. + /// The scale mode that determines how the current value should be scaled. + /// The underlying type of the value to convert. + /// Returns a representing the current value. + public static BigDecimal ToBigDecimal(this T value, int scale = default, ScaleMode mode = ScaleMode.Integral) where T : IBinaryInteger + { + return new BigDecimal(value.ToBigInteger(), scale, mode); + } + + /// + /// Converts the current value to a . + /// + /// The value to convert. + /// The mode that specifies whether the value should be converted using its binary or decimal representation. + /// Returns a new representing the current value. + public static BigDecimal ToBigDecimal(this float value, ConversionMode mode = default) + { + return new BigDecimal(value, mode); + } + + /// + /// Converts the current value to a . + /// + /// The value to convert. + /// The mode that specifies whether the value should be converted using its binary or decimal representation. + /// Returns a new representing the current value. + public static BigDecimal ToBigDecimal(this double value, ConversionMode mode = default) + { + return new BigDecimal(value, mode); + } + + /// + /// Converts the current value to a . + /// + /// The value to convert. + /// Returns a new representing the current value. + public static BigDecimal ToBigDecimal(this decimal value) + { + return new BigDecimal(value); + } + + /// + /// Converts the current value to a value. + /// + /// The value to convert. + /// The underlying type of the value to convert. + /// Returns a representing the current value. + public static BigInteger ToBigInteger(this T value) where T : IBinaryInteger + { + return BigInteger.CreateChecked(value); + } + + /// + /// Converts the current value to a . + /// + /// The value to convert. + /// The scale of the value. + /// The scale mode that determines how the current value should be scaled. + /// The underlying type of the value to convert. + /// Returns a new representing the current value. + public static decimal ToDecimal(this T value, int scale = default, ScaleMode mode = default) where T : IBinaryInteger + { + Require(scale.IsBetween(0, 28), "Scale must be between 0 and 28."); + RequireIsDefined(mode, nameof(mode)); + + BigInteger scaled = value.GetUnscaledInteger(scale, mode); + Check(scaled.IsBetween(MinDecimal, MaxDecimal), $"Value is either too large or too small to convert to {nameof(Decimal)}."); + + Int128 integer = Int128.Abs((Int128)scaled); + int lo = (int)integer; + int mid = (int)(integer >> 32); + int hi = (int)(integer >> 64); + + return new decimal(lo, mid, hi, T.IsNegative(value), (byte)scale); + } + + /// + /// Converts the current value to a value. + /// + /// The value to convert. + /// The desired scale of the specified value. + /// The scale mode that determines how the specified value should be scaled. + /// The underlying type. + /// Returns a representing the current value. + public static NumberInfo ToNumberInfo(this T value, int scale = default, ScaleMode mode = default) where T : IBinaryInteger + { + Require(scale >= 0, "Scale must be greater than or equal to zero", nameof(scale)); + RequireIsDefined(mode, nameof(mode)); + BigInteger unscaledValue = value.GetUnscaledInteger(scale, mode); + return new NumberInfo(unscaledValue, scale); + } + + /// + /// Converts the current value to a value. + /// + /// The value to convert. + /// The conversion mode that determines whether the current value should be converted from its binary or decimal representation. + /// Returns a representing the current value. + public static NumberInfo ToNumberInfo(this float value, ConversionMode mode = default) + { + RequireIsDefined(mode, nameof(mode)); + return Ieee754Converter.Convert(value, mode); + } + + /// + /// Converts the current value to a value. + /// + /// The value to convert. + /// The conversion mode that determines whether the current value should be converted from its binary or decimal representation. + /// Returns a representing the current value. + public static NumberInfo ToNumberInfo(this double value, ConversionMode mode = default) + { + RequireIsDefined(mode, nameof(mode)); + return Ieee754Converter.Convert(value, mode); + } + + /// + /// Converts the current value to a value. + /// + /// The value to convert. + /// Returns a representing the current value. + public static NumberInfo ToNumberInfo(this decimal value) + { + return new NumberInfo(value.GetUnscaledValue(), value.Scale); + } +} diff --git a/OnixLabs.Numerics/OnixLabs.Numerics.csproj b/OnixLabs.Numerics/OnixLabs.Numerics.csproj new file mode 100644 index 0000000..580f0fc --- /dev/null +++ b/OnixLabs.Numerics/OnixLabs.Numerics.csproj @@ -0,0 +1,49 @@ + + + net8.0 + OnixLabs.Numerics + ONIXLabs + ONIXLabs Numerics API for .NET + 6.0.0 + en + enable + true + Copyright © ONIXLabs 2020-2023 + https://github.com/onix-labs/onixlabs-dotnet + 6.0.0 + 12 + + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + embedded + true + true + true + Apache-2.0 + https://github.com/onix-labs/onixlabs-dotnet + README.md + true + true + git + https://github.com/onix-labs/onixlabs-dotnet + + + true + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + diff --git a/OnixLabs.Numerics/ScaleMode.cs b/OnixLabs.Numerics/ScaleMode.cs new file mode 100644 index 0000000..35cf410 --- /dev/null +++ b/OnixLabs.Numerics/ScaleMode.cs @@ -0,0 +1,31 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace OnixLabs.Numerics; + +/// +/// Specifies decimal scale modes. +/// +public enum ScaleMode +{ + /// + /// Specifies that unscaled values should be preserved; for example, 123 with a scale of 10 becomes 0.0000000123. + /// + Fractional, + + /// + /// Specifies that integer values should be preserved; for example, 123 with a scale of 10 becomes 123.0000000000. + /// + Integral +} diff --git a/OnixLabs.Playground/OnixLabs.Playground.csproj b/OnixLabs.Playground/OnixLabs.Playground.csproj index 2e0890c..7da8371 100644 --- a/OnixLabs.Playground/OnixLabs.Playground.csproj +++ b/OnixLabs.Playground/OnixLabs.Playground.csproj @@ -4,9 +4,14 @@ net8.0 enable 12 + true + + + false + diff --git a/OnixLabs.Playground/Program.cs b/OnixLabs.Playground/Program.cs index 6674ac3..1045f54 100644 --- a/OnixLabs.Playground/Program.cs +++ b/OnixLabs.Playground/Program.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,7 +16,7 @@ namespace OnixLabs.Playground; internal static class Program { - public static void Main() + private static void Main() { } } diff --git a/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj b/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj index c4fe399..e2195ca 100644 --- a/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj @@ -11,13 +11,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj index 5aba4ae..a8af21c 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj +++ b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj @@ -5,13 +5,13 @@ 12 - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/OnixLabs.Security.Cryptography/Sha3.Permute.cs b/OnixLabs.Security.Cryptography/Sha3.Permute.cs index 5021217..142b044 100644 --- a/OnixLabs.Security.Cryptography/Sha3.Permute.cs +++ b/OnixLabs.Security.Cryptography/Sha3.Permute.cs @@ -1,18 +1,18 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using System.Runtime.CompilerServices; +using System.Collections.Generic; namespace OnixLabs.Security.Cryptography; @@ -22,8 +22,7 @@ public abstract partial class Sha3 /// Performs the FIPS 202 SHA-3 permutation. /// /// The state upon which to perform the permutation. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void Permute(ulong[] state) + private static void Permute(IList state) { const int hashRounds = 24; @@ -49,7 +48,6 @@ private static void Permute(ulong[] state) return; - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] void Theta() { c0 = state[0] ^ state[5] ^ state[10] ^ state[15] ^ state[20]; @@ -91,7 +89,6 @@ void Theta() state[24] ^= d4; } - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] void RhoPi() { ulong final = RotateLeft(state[1], 1); @@ -122,7 +119,6 @@ void RhoPi() state[10] = final; } - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] void Chi() { for (int i = 0; i < 25; i += 5) @@ -141,13 +137,11 @@ void Chi() } } - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] void Iota(int round) { state[0] ^= roundConstants[round]; } - [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] ulong RotateLeft(ulong x, byte y) { return (x << y) | (x >> (64 - y)); diff --git a/onixlabs-dotnet.sln b/onixlabs-dotnet.sln index 60962fd..4bfcd86 100644 --- a/onixlabs-dotnet.sln +++ b/onixlabs-dotnet.sln @@ -1,11 +1,5 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Framework", "Framework", "{6E4FE7B0-5E44-4EB4-B64F-228645C4F79B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Playground", "Playground", "{039F52FD-BF3C-4E6A-B0AB-1F34E48ADBFF}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTests", "UnitTests", "{C1D7FFDA-A234-4A01-9371-19C68DD74C91}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Core", "OnixLabs.Core\OnixLabs.Core.csproj", "{1EDC1164-0205-433D-A356-00DAD4686264}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Playground", "OnixLabs.Playground\OnixLabs.Playground.csproj", "{23F9EB42-D9D4-4C43-9C99-3D2A1F8866B7}" @@ -20,7 +14,17 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Core.UnitTests.Dat EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Security.Cryptography.UnitTests.Data", "OnixLabs.Security.Cryptography.UnitTests.Data\OnixLabs.Security.Cryptography.UnitTests.Data.csproj", "{513CFC09-42E2-43C3-BB68-90640D78CDF4}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UnitTestData", "UnitTestData", "{5BA28E51-3E67-4081-BD69-5AE6885C8F2A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Numerics", "OnixLabs.Numerics\OnixLabs.Numerics.csproj", "{571D23F3-BC70-4646-A63C-844AED8291E3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Numerics.UnitTests", "OnixLabs.Numerics.UnitTests\OnixLabs.Numerics.UnitTests.csproj", "{5D14F804-600B-4CFF-8900-53F66D7821E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OnixLabs.Numerics.UnitTests.Data", "OnixLabs.Numerics.UnitTests.Data\OnixLabs.Numerics.UnitTests.Data.csproj", "{3A85C8CF-D5EF-4130-8CC0-8AAB07983707}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{45B3DB8D-3344-4CB5-A6B9-A587514056EA}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Numerics", "Numerics", "{95655D21-93CD-4A49-AAB2-E7A262E7B730}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Security.Cryptography", "Security.Cryptography", "{564C7FAB-BEA0-4B10-BE14-6C151E0ACE6E}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -28,14 +32,15 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution - {1EDC1164-0205-433D-A356-00DAD4686264} = {6E4FE7B0-5E44-4EB4-B64F-228645C4F79B} - {23F9EB42-D9D4-4C43-9C99-3D2A1F8866B7} = {039F52FD-BF3C-4E6A-B0AB-1F34E48ADBFF} - {893547DB-4EAA-4D1F-886F-0D6114F8601E} = {C1D7FFDA-A234-4A01-9371-19C68DD74C91} - {78FDB1BA-6545-41DE-99B8-F007C6A6B093} = {6E4FE7B0-5E44-4EB4-B64F-228645C4F79B} - {C3DE665B-5B02-41DE-8BB0-C53A1326E162} = {C1D7FFDA-A234-4A01-9371-19C68DD74C91} - {5BA28E51-3E67-4081-BD69-5AE6885C8F2A} = {C1D7FFDA-A234-4A01-9371-19C68DD74C91} - {E3FBC79F-7F5A-4ECF-9653-C0AB203FF5D5} = {5BA28E51-3E67-4081-BD69-5AE6885C8F2A} - {513CFC09-42E2-43C3-BB68-90640D78CDF4} = {5BA28E51-3E67-4081-BD69-5AE6885C8F2A} + {1EDC1164-0205-433D-A356-00DAD4686264} = {45B3DB8D-3344-4CB5-A6B9-A587514056EA} + {E3FBC79F-7F5A-4ECF-9653-C0AB203FF5D5} = {45B3DB8D-3344-4CB5-A6B9-A587514056EA} + {893547DB-4EAA-4D1F-886F-0D6114F8601E} = {45B3DB8D-3344-4CB5-A6B9-A587514056EA} + {571D23F3-BC70-4646-A63C-844AED8291E3} = {95655D21-93CD-4A49-AAB2-E7A262E7B730} + {5D14F804-600B-4CFF-8900-53F66D7821E8} = {95655D21-93CD-4A49-AAB2-E7A262E7B730} + {3A85C8CF-D5EF-4130-8CC0-8AAB07983707} = {95655D21-93CD-4A49-AAB2-E7A262E7B730} + {78FDB1BA-6545-41DE-99B8-F007C6A6B093} = {564C7FAB-BEA0-4B10-BE14-6C151E0ACE6E} + {C3DE665B-5B02-41DE-8BB0-C53A1326E162} = {564C7FAB-BEA0-4B10-BE14-6C151E0ACE6E} + {513CFC09-42E2-43C3-BB68-90640D78CDF4} = {564C7FAB-BEA0-4B10-BE14-6C151E0ACE6E} EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {1EDC1164-0205-433D-A356-00DAD4686264}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -66,5 +71,17 @@ Global {513CFC09-42E2-43C3-BB68-90640D78CDF4}.Debug|Any CPU.Build.0 = Debug|Any CPU {513CFC09-42E2-43C3-BB68-90640D78CDF4}.Release|Any CPU.ActiveCfg = Release|Any CPU {513CFC09-42E2-43C3-BB68-90640D78CDF4}.Release|Any CPU.Build.0 = Release|Any CPU + {571D23F3-BC70-4646-A63C-844AED8291E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {571D23F3-BC70-4646-A63C-844AED8291E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {571D23F3-BC70-4646-A63C-844AED8291E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {571D23F3-BC70-4646-A63C-844AED8291E3}.Release|Any CPU.Build.0 = Release|Any CPU + {5D14F804-600B-4CFF-8900-53F66D7821E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5D14F804-600B-4CFF-8900-53F66D7821E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5D14F804-600B-4CFF-8900-53F66D7821E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5D14F804-600B-4CFF-8900-53F66D7821E8}.Release|Any CPU.Build.0 = Release|Any CPU + {3A85C8CF-D5EF-4130-8CC0-8AAB07983707}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A85C8CF-D5EF-4130-8CC0-8AAB07983707}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A85C8CF-D5EF-4130-8CC0-8AAB07983707}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A85C8CF-D5EF-4130-8CC0-8AAB07983707}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/onixlabs-dotnet.sln.DotSettings b/onixlabs-dotnet.sln.DotSettings index 78825e9..70035ef 100644 --- a/onixlabs-dotnet.sln.DotSettings +++ b/onixlabs-dotnet.sln.DotSettings @@ -21,6 +21,7 @@ limitations under the License. True True True + True True True True @@ -39,6 +40,7 @@ limitations under the License. True True True + True True True True From de3d697cf4bb762fd17c3925644f097b1c0e169a Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Sat, 6 Apr 2024 00:04:24 +0100 Subject: [PATCH 10/14] update/text-base (#35) Updated text/base implementation. --- .../Text/Base32Base32HexAlphabetTests.cs | 20 +-- .../Text/Base32CrockfordAlphabetTests.cs | 20 +-- .../Text/Base32DefaultAlphabetTests.cs | 20 +-- .../Text/Base32ZBase32AlphabetTests.cs | 20 +-- .../Text/Base58DefaultAlphabetTests.cs | 16 +- .../Text/Base58FlickrAlphabetTests.cs | 16 +- .../Text/Base58RippleAlphabetTests.cs | 16 +- OnixLabs.Core/Extensions.String.cs | 14 ++ OnixLabs.Core/Text/Base16.Constants.cs | 15 +- OnixLabs.Core/Text/Base16.Create.cs | 84 ++++++++-- OnixLabs.Core/Text/Base16.Equatable.cs | 10 +- OnixLabs.Core/Text/Base16.Format.cs | 33 ++++ OnixLabs.Core/Text/Base16.Parse.cs | 80 +++++++++- OnixLabs.Core/Text/Base16.To.cs | 46 ++++-- OnixLabs.Core/Text/Base16.cs | 20 +-- OnixLabs.Core/Text/Base32.Constants.cs | 15 +- OnixLabs.Core/Text/Base32.Create.cs | 145 ++++++------------ OnixLabs.Core/Text/Base32.Equatable.cs | 14 +- OnixLabs.Core/Text/Base32.Format.cs | 33 ++++ OnixLabs.Core/Text/Base32.Parse.cs | 70 +++++++-- OnixLabs.Core/Text/Base32.To.cs | 49 ++++-- OnixLabs.Core/Text/Base32.cs | 36 ++--- OnixLabs.Core/Text/Base32Alphabet.cs | 62 -------- .../Text/{Base32.Codec.cs => Base32Codec.cs} | 43 ++---- OnixLabs.Core/Text/Base32FormatInfo.cs | 80 ++++++++++ OnixLabs.Core/Text/Base58.Checksum.cs | 9 +- OnixLabs.Core/Text/Base58.Constants.cs | 11 +- OnixLabs.Core/Text/Base58.Create.cs | 94 +++++++----- OnixLabs.Core/Text/Base58.Equatable.cs | 11 +- OnixLabs.Core/Text/Base58.Format.cs | 33 ++++ OnixLabs.Core/Text/Base58.Parse.cs | 138 +++++++++++++---- OnixLabs.Core/Text/Base58.To.cs | 57 ++++--- OnixLabs.Core/Text/Base58.cs | 29 ++-- OnixLabs.Core/Text/Base58Alphabet.cs | 52 ------- .../Text/{Base58.Codec.cs => Base58Codec.cs} | 24 ++- OnixLabs.Core/Text/Base58FormatInfo.cs | 67 ++++++++ OnixLabs.Core/Text/Base64.Constants.cs | 11 +- OnixLabs.Core/Text/Base64.Create.cs | 84 ++++++++-- OnixLabs.Core/Text/Base64.Equatable.cs | 14 +- OnixLabs.Core/Text/Base64.Format.cs | 33 ++++ OnixLabs.Core/Text/Base64.Parse.cs | 80 +++++++++- OnixLabs.Core/Text/Base64.To.cs | 44 ++++-- OnixLabs.Core/Text/Base64.cs | 20 +-- OnixLabs.Core/Text/IBase.cs | 93 ----------- OnixLabs.Core/Text/IBaseRepresentation.cs | 136 ++++++++++++++++ OnixLabs.Numerics/BigDecimal.Format.cs | 4 +- .../DigitalSignature.To.cs | 30 +--- OnixLabs.Security.Cryptography/Hash.To.cs | 30 +--- .../PrivateKey.To.cs | 30 +--- .../PublicKey.To.cs | 30 +--- onixlabs-dotnet.sln.DotSettings | 1 + 51 files changed, 1323 insertions(+), 819 deletions(-) create mode 100644 OnixLabs.Core/Text/Base16.Format.cs create mode 100644 OnixLabs.Core/Text/Base32.Format.cs delete mode 100644 OnixLabs.Core/Text/Base32Alphabet.cs rename OnixLabs.Core/Text/{Base32.Codec.cs => Base32Codec.cs} (86%) create mode 100644 OnixLabs.Core/Text/Base32FormatInfo.cs create mode 100644 OnixLabs.Core/Text/Base58.Format.cs delete mode 100644 OnixLabs.Core/Text/Base58Alphabet.cs rename OnixLabs.Core/Text/{Base58.Codec.cs => Base58Codec.cs} (88%) create mode 100644 OnixLabs.Core/Text/Base58FormatInfo.cs create mode 100644 OnixLabs.Core/Text/Base64.Format.cs delete mode 100644 OnixLabs.Core/Text/IBase.cs create mode 100644 OnixLabs.Core/Text/IBaseRepresentation.cs diff --git a/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs index f4f5dab..2f80098 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,8 +23,8 @@ public sealed class Base32Base32HexAlphabetTests public void Base32ValuesShouldBeIdentical() { // Given - Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Base32Hex); - Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Base32Hex); + Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz"); + Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz"); // When int hashCodeA = a.GetHashCode(); @@ -41,10 +41,10 @@ public void Base32ValuesShouldBeIdentical() public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) { // Given - Base32 candidate = Base32.Create(value, Base32Alphabet.Base32Hex, true); + Base32 candidate = Base32.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString("P", Base32FormatInfo.Base32Hex); // Then Assert.Equal(expected, actual); @@ -57,10 +57,10 @@ public void CreateShouldProduceExpectedResultWithPadding(string expected, string public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) { // Given - Base32 candidate = Base32.Create(value, Base32Alphabet.Base32Hex, false); + Base32 candidate = Base32.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString(null, Base32FormatInfo.Base32Hex); // Then Assert.Equal(expected, actual); @@ -73,7 +73,7 @@ public void CreateShouldProduceExpectedResultWithoutPadding(string expected, str public void ParseShouldProduceExpectedResult(string expected, string value) { // Given - Base32 candidate = Base32.Parse(value, Base32Alphabet.Base32Hex); + Base32 candidate = Base32.Parse(value, Base32FormatInfo.Base32Hex); // When string actual = candidate.ToPlainTextString(); diff --git a/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs index 5981312..e167b77 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,8 +23,8 @@ public sealed class Base32CrockfordAlphabetTests public void Base32ValuesShouldBeIdentical() { // Given - Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Crockford); - Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Crockford); + Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz"); + Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz"); // When int hashCodeA = a.GetHashCode(); @@ -41,10 +41,10 @@ public void Base32ValuesShouldBeIdentical() public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) { // Given - Base32 candidate = Base32.Create(value, Base32Alphabet.Crockford, true); + Base32 candidate = Base32.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString("P", Base32FormatInfo.Crockford); // Then Assert.Equal(expected, actual); @@ -57,10 +57,10 @@ public void CreateShouldProduceExpectedResultWithPadding(string expected, string public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) { // Given - Base32 candidate = Base32.Create(value, Base32Alphabet.Crockford, false); + Base32 candidate = Base32.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString(null, Base32FormatInfo.Crockford); // Then Assert.Equal(expected, actual); @@ -73,7 +73,7 @@ public void CreateShouldProduceExpectedResultWithoutPadding(string expected, str public void ParseShouldProduceExpectedResult(string expected, string value) { // Given - Base32 candidate = Base32.Parse(value, Base32Alphabet.Crockford); + Base32 candidate = Base32.Parse(value, Base32FormatInfo.Crockford); // When string actual = candidate.ToPlainTextString(); diff --git a/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs index ba75917..2237989 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,8 +23,8 @@ public sealed class Base32DefaultAlphabetTests public void Base32ValuesShouldBeIdentical() { // Given - Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Default); - Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.Default); + Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz"); + Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz"); // When int hashCodeA = a.GetHashCode(); @@ -41,10 +41,10 @@ public void Base32ValuesShouldBeIdentical() public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) { // Given - Base32 candidate = Base32.Create(value, Base32Alphabet.Default, true); + Base32 candidate = Base32.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString("P", Base32FormatInfo.Default); // Then Assert.Equal(expected, actual); @@ -57,10 +57,10 @@ public void CreateShouldProduceExpectedResultWithPadding(string expected, string public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) { // Given - Base32 candidate = Base32.Create(value, Base32Alphabet.Default, false); + Base32 candidate = Base32.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString(null, Base32FormatInfo.Default); // Then Assert.Equal(expected, actual); @@ -73,7 +73,7 @@ public void CreateShouldProduceExpectedResultWithoutPadding(string expected, str public void ParseShouldProduceExpectedResult(string expected, string value) { // Given - Base32 candidate = Base32.Parse(value, Base32Alphabet.Default); + Base32 candidate = Base32.Parse(value, Base32FormatInfo.Default); // When string actual = candidate.ToPlainTextString(); diff --git a/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs index 9b4a129..b48f0e8 100644 --- a/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,8 +23,8 @@ public sealed class Base32ZBase32AlphabetTests public void Base32ValuesShouldBeIdentical() { // Given - Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.ZBase32); - Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz", Base32Alphabet.ZBase32); + Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz"); + Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz"); // When int hashCodeA = a.GetHashCode(); @@ -41,10 +41,10 @@ public void Base32ValuesShouldBeIdentical() public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) { // Given - Base32 candidate = Base32.Create(value, Base32Alphabet.ZBase32, true); + Base32 candidate = Base32.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString("P", Base32FormatInfo.ZBase32); // Then Assert.Equal(expected, actual); @@ -57,10 +57,10 @@ public void CreateShouldProduceExpectedResultWithPadding(string expected, string public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) { // Given - Base32 candidate = Base32.Create(value, Base32Alphabet.ZBase32, false); + Base32 candidate = Base32.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString(null, Base32FormatInfo.ZBase32); // Then Assert.Equal(expected, actual); @@ -73,7 +73,7 @@ public void CreateShouldProduceExpectedResultWithoutPadding(string expected, str public void ParseShouldProduceExpectedResult(string expected, string value) { // Given - Base32 candidate = Base32.Parse(value, Base32Alphabet.ZBase32); + Base32 candidate = Base32.Parse(value, Base32FormatInfo.ZBase32); // When string actual = candidate.ToPlainTextString(); diff --git a/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs index 6cd71fd..db56568 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,8 +23,8 @@ public sealed class Base58DefaultAlphabetTests public void Base58ValuesShouldBeIdentical() { // Given - Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Default); - Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Default); + Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz"); + Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz"); // When int hashCodeA = a.GetHashCode(); @@ -41,10 +41,10 @@ public void Base58ValuesShouldBeIdentical() public void CreateShouldProduceExpectedResult(string expected, string value) { // Given - Base58 candidate = Base58.Create(value, Base58Alphabet.Default); + Base58 candidate = Base58.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString(null, Base58FormatInfo.Default); // Then Assert.Equal(expected, actual); @@ -57,7 +57,7 @@ public void CreateShouldProduceExpectedResult(string expected, string value) public void ParseShouldProduceExpectedResult(string expected, string value) { // Given - Base58 candidate = Base58.Parse(value, Base58Alphabet.Default); + Base58 candidate = Base58.Parse(value, Base58FormatInfo.Default); // When string actual = candidate.ToPlainTextString(); diff --git a/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs index 50ee0aa..1a5698e 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,8 +23,8 @@ public sealed class Base58FlickrAlphabetTests public void Base58ValuesShouldBeIdentical() { // Given - Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Flickr); - Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Flickr); + Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz"); + Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz"); // When int hashCodeA = a.GetHashCode(); @@ -41,10 +41,10 @@ public void Base58ValuesShouldBeIdentical() public void CreateShouldProduceExpectedResult(string expected, string value) { // Given - Base58 candidate = Base58.Create(value, Base58Alphabet.Flickr); + Base58 candidate = Base58.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString(null, Base58FormatInfo.Flickr); // Then Assert.Equal(expected, actual); @@ -57,7 +57,7 @@ public void CreateShouldProduceExpectedResult(string expected, string value) public void ParseShouldProduceExpectedResult(string expected, string value) { // Given - Base58 candidate = Base58.Parse(value, Base58Alphabet.Flickr); + Base58 candidate = Base58.Parse(value, Base58FormatInfo.Flickr); // When string actual = candidate.ToPlainTextString(); diff --git a/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs index b5b35ae..b10067f 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,8 +23,8 @@ public sealed class Base58RippleAlphabetTests public void Base58ValuesShouldBeIdentical() { // Given - Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Ripple); - Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz", Base58Alphabet.Ripple); + Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz"); + Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz"); // When int hashCodeA = a.GetHashCode(); @@ -41,10 +41,10 @@ public void Base58ValuesShouldBeIdentical() public void CreateShouldProduceExpectedResult(string expected, string value) { // Given - Base58 candidate = Base58.Create(value, Base58Alphabet.Ripple); + Base58 candidate = Base58.Create(value); // When - string actual = candidate.ToString(); + string actual = candidate.ToString(null, Base58FormatInfo.Ripple); // Then Assert.Equal(expected, actual); @@ -57,7 +57,7 @@ public void CreateShouldProduceExpectedResult(string expected, string value) public void ParseShouldProduceExpectedResult(string expected, string value) { // Given - Base58 candidate = Base58.Parse(value, Base58Alphabet.Ripple); + Base58 candidate = Base58.Parse(value, Base58FormatInfo.Ripple); // When string actual = candidate.ToPlainTextString(); diff --git a/OnixLabs.Core/Extensions.String.cs b/OnixLabs.Core/Extensions.String.cs index d3c193a..3c050c0 100644 --- a/OnixLabs.Core/Extensions.String.cs +++ b/OnixLabs.Core/Extensions.String.cs @@ -250,6 +250,20 @@ public static TimeOnly ToTimeOnly(this string value, IFormatProvider? provider = return TimeOnly.Parse(value, provider, styles); } + /// + /// Copies the contents of the current into the destination . + /// + /// The current value to copy. + /// The into which to copy the current contents. + /// The number of characters written to the destination . + /// Returns if the data was copied into the destination span; otherwise, if the destination was too short. + public static bool TryCopyTo(this string value, Span destination, out int charsWritten) + { + bool result = value.TryCopyTo(destination); + charsWritten = result ? value.Length : 0; + return result; + } + /// /// Converts the current between the specified before and after values. /// diff --git a/OnixLabs.Core/Text/Base16.Constants.cs b/OnixLabs.Core/Text/Base16.Constants.cs index 640d8b9..268622f 100644 --- a/OnixLabs.Core/Text/Base16.Constants.cs +++ b/OnixLabs.Core/Text/Base16.Constants.cs @@ -1,19 +1,17 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core.Collections; - namespace OnixLabs.Core.Text; public readonly partial struct Base16 @@ -21,5 +19,10 @@ public readonly partial struct Base16 /// /// Gets an empty value. /// - public static Base16 Empty => Create(EmptyArray()); + public static Base16 Empty => new([]); + + /// + /// Gets the default Base-16 format. + /// + private const char DefaultFormat = 'L'; } diff --git a/OnixLabs.Core/Text/Base16.Create.cs b/OnixLabs.Core/Text/Base16.Create.cs index e9edc77..0675c39 100644 --- a/OnixLabs.Core/Text/Base16.Create.cs +++ b/OnixLabs.Core/Text/Base16.Create.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,35 +20,85 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base16 { /// - /// Creates a instance from the specified array. + /// Creates a new value from the specified value. /// - /// The underlying value. - /// Returns a new instance. + /// The value from which to create a new value. + /// Returns a new value from the specified value. public static Base16 Create(byte[] value) { return new Base16(value); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value. /// - /// The underlying value. - /// Returns a new instance. - public static Base16 Create(ReadOnlySpan value) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base16 Create(ReadOnlySpan value) + { + return Create(value.ToArray()); + } + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base16 Create(string value) + { + return Create(value.ToCharArray(), Encoding.Default); + } + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base16 Create(string value, Encoding encoding) + { + return Create(value.ToCharArray(), encoding); + } + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base16 Create(char[] value) { return Create(value, Encoding.Default); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base16 Create(char[] value, Encoding encoding) + { + return Create(encoding.GetBytes(value)); + } + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base16 Create(ReadOnlySpan value) + { + return Create(value.ToArray(), Encoding.Default); + } + + /// + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. public static Base16 Create(ReadOnlySpan value, Encoding encoding) { - // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. - byte[] bytes = encoding.GetBytes(value.ToArray()); - return Create(bytes); + return Create(value.ToArray(), encoding); } } diff --git a/OnixLabs.Core/Text/Base16.Equatable.cs b/OnixLabs.Core/Text/Base16.Equatable.cs index 1068f0e..22150bf 100644 --- a/OnixLabs.Core/Text/Base16.Equatable.cs +++ b/OnixLabs.Core/Text/Base16.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,7 +27,7 @@ public readonly partial struct Base16 /// Returns true if the object is equal to the current instance; otherwise, false. public bool Equals(Base16 other) { - return other.Value.SequenceEqual(Value); + return value.SequenceEqual(other.value); } /// @@ -46,7 +46,7 @@ public override bool Equals(object? obj) /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(Value.GetContentHashCode()); + return HashCode.Combine(value.GetContentHashCode()); } /// diff --git a/OnixLabs.Core/Text/Base16.Format.cs b/OnixLabs.Core/Text/Base16.Format.cs new file mode 100644 index 0000000..c219429 --- /dev/null +++ b/OnixLabs.Core/Text/Base16.Format.cs @@ -0,0 +1,33 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +public readonly partial struct Base16 +{ + /// + /// Tries to format the value of the current instance into the provided span of characters. + /// + /// The span in which to write this instance's value formatted as a span of characters. + /// When this method returns, contains the number of characters that were written in . + /// A span containing the characters that represent a standard or custom format string that defines the acceptable format for . + /// An optional object that supplies culture-specific formatting information for . + /// Returns if the formatting was successful; otherwise, . + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + return ToString(format, provider).TryCopyTo(destination, out charsWritten); + } +} diff --git a/OnixLabs.Core/Text/Base16.Parse.cs b/OnixLabs.Core/Text/Base16.Parse.cs index 216b40a..fc850d3 100644 --- a/OnixLabs.Core/Text/Base16.Parse.cs +++ b/OnixLabs.Core/Text/Base16.Parse.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,13 +19,77 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base16 { /// - /// Parses a Base-16 (hexadecimal) value into a instance. + /// Parses a Base-16 (Hexadecimal) value into a value. /// - /// The Base-16 (hexadecimal) value to parse. + /// The Base-16 (Hexadecimal) value to parse. + /// + /// An object that provides format-specific information about the specified value. + /// The parameter is ignored by the current implementation of . + /// /// Returns a new instance. - public static Base16 Parse(ReadOnlySpan value) + public static Base16 Parse(string value, IFormatProvider? provider = null) { - byte[] bytes = Convert.FromHexString(value); - return Create(bytes); + return Parse(value.AsSpan(), provider); + } + + /// + /// Parses a Base-16 (Hexadecimal) value into a value. + /// + /// The Base-16 (Hexadecimal) value to parse. + /// + /// An object that provides format-specific information about the specified value. + /// The parameter is ignored by the current implementation of . + /// + /// Returns a new instance. + public static Base16 Parse(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryParse(value, provider, out Base16 result)) return result; + throw new FormatException($"The input string '{value}' was not in a correct format."); + } + + /// + /// Tries to parse the specified Base-16 (Hexadecimal) value into a value. + /// + /// The Base-16 (Hexadecimal) value to parse. + /// + /// An object that provides format-specific information about the specified value. + /// The parameter is ignored by the current implementation of . + /// + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, IFormatProvider? provider, out Base16 result) + { + return TryParse(value.AsSpan(), provider, out result); + } + + /// + /// Tries to parse the specified Base-16 (Hexadecimal) value into a value. + /// + /// The Base-16 (Hexadecimal) value to parse. + /// + /// An object that provides format-specific information about the specified value. + /// The parameter is ignored by the current implementation of . + /// + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base16 result) + { + try + { + byte[] bytes = Convert.FromHexString(value); + result = Create(bytes); + return true; + } + catch + { + result = Empty; + return false; + } } } diff --git a/OnixLabs.Core/Text/Base16.To.cs b/OnixLabs.Core/Text/Base16.To.cs index 464c2bd..e24db9d 100644 --- a/OnixLabs.Core/Text/Base16.To.cs +++ b/OnixLabs.Core/Text/Base16.To.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,26 +25,26 @@ public readonly partial struct Base16 /// Returns a array that represents the current object. public byte[] ToByteArray() { - return Value.Copy(); + return value.Copy(); } /// - /// Returns a that represents the current object in plain text. + /// Gets the plain-text representation of the current value, using the default . /// - /// Returns a that represents the current object in plain text. + /// Returns the plain-text representation of the current value, using the default . public string ToPlainTextString() { return ToPlainTextString(Encoding.Default); } /// - /// Returns a that represents the current object in plain text. + /// Gets the plain-text representation of the current value. /// - /// The encoding to use to obtain the underlying value. - /// Returns a that represents the current object in plain text. + /// The which will be used to obtain a from the current value. + /// Returns the plain-text representation of the current value. public string ToPlainTextString(Encoding encoding) { - return encoding.GetString(Value); + return encoding.GetString(value); } /// @@ -53,6 +53,30 @@ public string ToPlainTextString(Encoding encoding) /// Returns a that represents the current object. public override string ToString() { - return Convert.ToHexString(Value).ToLower(); + return ToString([DefaultFormat]); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(string? format, IFormatProvider? formatProvider = null) + { + return ToString(format.AsSpan(), formatProvider); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + { + char specifier = char.ToUpperInvariant(format.IsEmpty || format.IsWhiteSpace() ? DefaultFormat : format[0]); + string result = Convert.ToHexString(value); + return specifier == DefaultFormat ? result.ToLower() : result; } } diff --git a/OnixLabs.Core/Text/Base16.cs b/OnixLabs.Core/Text/Base16.cs index 80373ff..5ec68c2 100644 --- a/OnixLabs.Core/Text/Base16.cs +++ b/OnixLabs.Core/Text/Base16.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,19 +17,19 @@ namespace OnixLabs.Core.Text; /// /// Represents a Base-16 (hexadecimal) value. /// -public readonly partial struct Base16 : IBase +public readonly partial struct Base16 : IBaseRepresentation { + /// + /// The underlying value. + /// + private readonly byte[] value; + /// /// Initializes a new instance of the struct. /// /// The underlying value. private Base16(byte[] value) { - Value = value.Copy(); + this.value = value.Copy(); } - - /// - /// Gets the underlying value. - /// - private byte[] Value { get; } } diff --git a/OnixLabs.Core/Text/Base32.Constants.cs b/OnixLabs.Core/Text/Base32.Constants.cs index 4d1a094..c0d9144 100644 --- a/OnixLabs.Core/Text/Base32.Constants.cs +++ b/OnixLabs.Core/Text/Base32.Constants.cs @@ -1,30 +1,23 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core.Collections; - namespace OnixLabs.Core.Text; public readonly partial struct Base32 { - /// - /// Gets the default padding option when creating new Base-32 instances. - /// - private const bool DefaultPadding = true; - /// /// Gets an empty value. /// - public static Base32 Empty => Create(EmptyArray()); + public static Base32 Empty => new([]); } diff --git a/OnixLabs.Core/Text/Base32.Create.cs b/OnixLabs.Core/Text/Base32.Create.cs index 2892bcb..ee9cd68 100644 --- a/OnixLabs.Core/Text/Base32.Create.cs +++ b/OnixLabs.Core/Text/Base32.Create.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,140 +20,85 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base32 { /// - /// Creates a instance from the specified array. + /// Creates a new value from the specified value. /// - /// The underlying value. - /// Returns a new instance. + /// The value from which to create a new value. + /// Returns a new value from the specified value. public static Base32 Create(byte[] value) { - return Create(value, Base32Alphabet.Default); + return new Base32(value); } /// - /// Creates a instance from the specified array. + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(byte[] value, Base32Alphabet alphabet) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base32 Create(ReadOnlySpan value) { - return Create(value, alphabet, DefaultPadding); + return Create(value.ToArray()); } /// - /// Creates a instance from the specified array. + /// Creates a new value from the specified value, using the default . /// - /// The underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(byte[] value, bool padding) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base32 Create(string value) { - return Create(value, Base32Alphabet.Default, padding); + return Create(value.ToCharArray(), Encoding.Default); } /// - /// Creates a instance from the specified array. + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(byte[] value, Base32Alphabet alphabet, bool padding) + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base32 Create(string value, Encoding encoding) { - return new Base32(value, alphabet, padding); + return Create(value.ToCharArray(), encoding); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value, using the default . /// - /// The underlying value. - /// Returns a new instance. - public static Base32 Create(ReadOnlySpan value) - { - return Create(value, Encoding.Default, Base32Alphabet.Default, DefaultPadding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base32 Create(ReadOnlySpan value, Encoding encoding) - { - return Create(value, encoding, Base32Alphabet.Default, DefaultPadding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(ReadOnlySpan value, bool padding) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base32 Create(char[] value) { - return Create(value, Encoding.Default, Base32Alphabet.Default, padding); + return Create(value, Encoding.Default); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(ReadOnlySpan value, Encoding encoding, bool padding) + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base32 Create(char[] value, Encoding encoding) { - return Create(value, encoding, Base32Alphabet.Default, padding); + return Create(encoding.GetBytes(value)); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value, using the default . /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(ReadOnlySpan value, Base32Alphabet alphabet) - { - return Create(value, Encoding.Default, alphabet); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(ReadOnlySpan value, Encoding encoding, Base32Alphabet alphabet) - { - return Create(value, encoding, alphabet, DefaultPadding); - } - - /// - /// Creates a instance from the specified . - /// - /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(ReadOnlySpan value, Base32Alphabet alphabet, bool padding) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base32 Create(ReadOnlySpan value) { - return Create(value, Encoding.Default, alphabet, padding); + return Create(value.ToArray(), Encoding.Default); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a new instance. - public static Base32 Create(ReadOnlySpan value, Encoding encoding, Base32Alphabet alphabet, bool padding) + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base32 Create(ReadOnlySpan value, Encoding encoding) { - // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. - byte[] bytes = encoding.GetBytes(value.ToArray()); - return Create(bytes, alphabet, padding); + return Create(value.ToArray(), encoding); } } diff --git a/OnixLabs.Core/Text/Base32.Equatable.cs b/OnixLabs.Core/Text/Base32.Equatable.cs index 31c4bf0..086d9d7 100644 --- a/OnixLabs.Core/Text/Base32.Equatable.cs +++ b/OnixLabs.Core/Text/Base32.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,7 +27,7 @@ public readonly partial struct Base32 /// Returns true if the object is equal to the current instance; otherwise, false. public bool Equals(Base32 other) { - return other.Value.SequenceEqual(Value) && other.Alphabet == Alphabet && other.Padding == Padding; + return value.SequenceEqual(other.value); } /// @@ -46,7 +46,7 @@ public override bool Equals(object? obj) /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(Value.GetContentHashCode()); + return HashCode.Combine(value.GetContentHashCode()); } /// @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// Returns true if the instances are equal; otherwise, false. public static bool operator ==(Base32 left, Base32 right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// Returns true if the instances are not equal; otherwise, false. public static bool operator !=(Base32 left, Base32 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base32.Format.cs b/OnixLabs.Core/Text/Base32.Format.cs new file mode 100644 index 0000000..0aef63a --- /dev/null +++ b/OnixLabs.Core/Text/Base32.Format.cs @@ -0,0 +1,33 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +public readonly partial struct Base32 +{ + /// + /// Tries to format the value of the current instance into the provided span of characters. + /// + /// The span in which to write this instance's value formatted as a span of characters. + /// When this method returns, contains the number of characters that were written in . + /// A span containing the characters that represent a standard or custom format string that defines the acceptable format for . + /// An optional object that supplies culture-specific formatting information for . + /// Returns if the formatting was successful; otherwise, . + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + return ToString(format, provider).TryCopyTo(destination, out charsWritten); + } +} diff --git a/OnixLabs.Core/Text/Base32.Parse.cs b/OnixLabs.Core/Text/Base32.Parse.cs index 37acd54..cee39fd 100644 --- a/OnixLabs.Core/Text/Base32.Parse.cs +++ b/OnixLabs.Core/Text/Base32.Parse.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,25 +19,67 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base32 { /// - /// Parses a Base-32 value into a instance. + /// Parses a Base-32 value into a value. /// - /// The Base-16 (hexadecimal) value to parse. + /// The Base-32 value to parse. + /// An object that provides format-specific information about the specified value. /// Returns a new instance. - public static Base32 Parse(ReadOnlySpan value) + public static Base32 Parse(string value, IFormatProvider? provider = null) { - return Parse(value, Base32Alphabet.Default); + return Parse(value.AsSpan(), provider); } /// - /// Parses a Base-32 value into a instance. + /// Parses a Base-32 value into a value. /// - /// The Base-16 (hexadecimal) value to parse. - /// The alphabet that will be used for Base-32 encoding and decoding operations. + /// The Base-32 value to parse. + /// An object that provides format-specific information about the specified value. /// Returns a new instance. - public static Base32 Parse(ReadOnlySpan value, Base32Alphabet alphabet) + public static Base32 Parse(ReadOnlySpan value, IFormatProvider? provider = null) { - bool padding = value.Contains('='); - byte[] bytes = Decode(value, alphabet.Alphabet, padding); - return Create(bytes, padding); + if (TryParse(value, provider, out Base32 result)) return result; + throw new FormatException($"The input string '{value}' was not in a correct format."); + } + + /// + /// Tries to parse the specified Base-32 value into a value. + /// + /// The Base-32 value to parse. + /// An object that provides format-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, IFormatProvider? provider, out Base32 result) + { + return TryParse(value.AsSpan(), provider, out result); + } + + /// + /// Tries to parse the specified Base-32 value into a value. + /// + /// The Base-32 value to parse. + /// An object that provides format-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base32 result) + { + try + { + Base32FormatInfo info = provider as Base32FormatInfo ?? Base32FormatInfo.Default; + bool padding = value.Contains('='); + byte[] bytes = Base32Codec.Decode(value, info.Alphabet, padding); + result = Create(bytes); + return true; + } + catch + { + result = Empty; + return false; + } } } diff --git a/OnixLabs.Core/Text/Base32.To.cs b/OnixLabs.Core/Text/Base32.To.cs index 44f1526..5542564 100644 --- a/OnixLabs.Core/Text/Base32.To.cs +++ b/OnixLabs.Core/Text/Base32.To.cs @@ -1,17 +1,18 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Text; namespace OnixLabs.Core.Text; @@ -24,34 +25,58 @@ public readonly partial struct Base32 /// Returns a array that represents the current object. public byte[] ToByteArray() { - return Value.Copy(); + return value.Copy(); } /// - /// Returns a that represents the current object in plain text. + /// Gets the plain-text representation of the current value, using the default . /// - /// Returns a that represents the current object in plain text. + /// Returns the plain-text representation of the current value, using the default . public string ToPlainTextString() { return ToPlainTextString(Encoding.Default); } /// - /// Returns a that represents the current object in plain text. + /// Gets the plain-text representation of the current value. /// - /// The encoding to use to obtain the underlying value. - /// Returns a that represents the current object in plain text. + /// The which will be used to obtain a from the current value. + /// Returns the plain-text representation of the current value. public string ToPlainTextString(Encoding encoding) { - return encoding.GetString(Value); + return encoding.GetString(value); } /// /// Returns a that represents the current object. /// - /// A that represents the current object. + /// Returns a that represents the current object. public override string ToString() { - return Encode(Value, Alphabet.Alphabet, Padding); + return ToString(null); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(string? format, IFormatProvider? formatProvider = null) + { + return ToString(format.AsSpan(), formatProvider); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + { + Base32FormatInfo info = formatProvider as Base32FormatInfo ?? Base32FormatInfo.Default; + bool padding = char.ToUpperInvariant(format.IsEmpty || format.IsWhiteSpace() ? default : format[0]) == 'P'; + return Base32Codec.Encode(value, info.Alphabet, padding); } } diff --git a/OnixLabs.Core/Text/Base32.cs b/OnixLabs.Core/Text/Base32.cs index 597f022..a25cc85 100644 --- a/OnixLabs.Core/Text/Base32.cs +++ b/OnixLabs.Core/Text/Base32.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,33 +17,19 @@ namespace OnixLabs.Core.Text; /// /// Represents a Base-32 value. /// -public readonly partial struct Base32 : IBase +public readonly partial struct Base32 : IBaseRepresentation { + /// + /// The underlying value. + /// + private readonly byte[] value; + /// /// Initializes a new instance of the struct. /// /// The underlying value. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - private Base32(byte[] value, Base32Alphabet alphabet, bool padding) + private Base32(byte[] value) { - Value = value.Copy(); - Alphabet = alphabet; - Padding = padding; + this.value = value.Copy(); } - - /// - /// Gets the underlying value. - /// - private byte[] Value { get; } - - /// - /// Gets the alphabet that will be used for Base-32 encoding and decoding operations. - /// - private Base32Alphabet Alphabet { get; } - - /// - /// Gets a value that determines whether padding should be applied for Base-32 encoding and decoding operations. - /// - private bool Padding { get; } } diff --git a/OnixLabs.Core/Text/Base32Alphabet.cs b/OnixLabs.Core/Text/Base32Alphabet.cs deleted file mode 100644 index 6ea1ebd..0000000 --- a/OnixLabs.Core/Text/Base32Alphabet.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Core.Text; - -/// -/// Specifies the supported Base-32 alphabets. -/// -public sealed class Base32Alphabet : Enumeration -{ - /// - /// The default (RFC-4648) Base-32 alphabet. - /// - public static Base32Alphabet Default => new(0, nameof(Default), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); - - /// - /// The Z-Base-32 alphabet. - /// - public static Base32Alphabet ZBase32 => new(1, nameof(ZBase32), "ybndrfg8ejkmcpqxot1uwisza345h769"); - - /// - /// The Geohash Base-32 alphabet. - /// - public static Base32Alphabet GeoHash => new(2, nameof(GeoHash), "0123456789bcdefghjkmnpqrstuvwxyz"); - - /// - /// The Crockford Base-32 alphabet. - /// - public static Base32Alphabet Crockford => new(3, nameof(Crockford), "0123456789ABCDEFGHJKMNPQRSTVWXYZ"); - - /// - /// The Base-32 Hex alphabet. - /// - public static Base32Alphabet Base32Hex => new(4, nameof(Base32Hex), "0123456789ABCDEFGHIJKLMNOPQRSTUV"); - - /// - /// Initializes a new instance of the class. - /// - /// The value of the enumeration entry. - /// The name of the enumeration entry. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - private Base32Alphabet(int value, string name, string alphabet) : base(value, name) - { - Alphabet = alphabet; - } - - /// - /// Gets the alphabet that will be used for Base-32 encoding and decoding operations. - /// - public string Alphabet { get; } -} diff --git a/OnixLabs.Core/Text/Base32.Codec.cs b/OnixLabs.Core/Text/Base32Codec.cs similarity index 86% rename from OnixLabs.Core/Text/Base32.Codec.cs rename to OnixLabs.Core/Text/Base32Codec.cs index b8747e0..1a0ed87 100644 --- a/OnixLabs.Core/Text/Base32.Codec.cs +++ b/OnixLabs.Core/Text/Base32Codec.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -13,11 +13,15 @@ // limitations under the License. using System; +using System.Collections.Generic; using System.Text; namespace OnixLabs.Core.Text; -public readonly partial struct Base32 +/// +/// Represents a Base-32 encoder/decoder. +/// +internal static class Base32Codec { /// /// The Base-32 input data size. @@ -36,21 +40,18 @@ public readonly partial struct Base32 /// The Base-32 alphabet to use for encoding. /// Determines whether padding should be applied for Base-32 encoding and decoding operations. /// Returns a Base-32 encoded string. - private static string Encode(byte[] value, string alphabet, bool padding) + public static string Encode(IReadOnlyList value, string alphabet, bool padding) { - if (value.Length == 0) - { - return string.Empty; - } + if (value.Count == 0) return string.Empty; - StringBuilder builder = new(value.Length * InputSize / OutputSize); + StringBuilder builder = new(value.Count * InputSize / OutputSize); int inputPosition = 0; int inputSubPosition = 0; byte outputPosition = 0; int outputSubPosition = 0; - while (inputPosition < value.Length) + while (inputPosition < value.Count) { int availableBits = Math.Min(InputSize - inputSubPosition, OutputSize - outputSubPosition); @@ -79,42 +80,32 @@ private static string Encode(byte[] value, string alphabet, bool padding) outputPosition &= 0x1F; builder.Append(alphabet[outputPosition]); - while (padding && builder.Length % InputSize != 0) - { - builder.Append('='); - } + while (padding && builder.Length % InputSize != 0) builder.Append('='); return builder.ToString(); } /// - /// Decodes a Base-32 into a byte array. + /// Decodes a Base-32 into a byte array. /// /// The value to decode. /// The Base-32 alphabet to use for decoding. /// Determines whether padding should be applied for Base-32 encoding and decoding operations. /// Returns a byte array. /// If the Base-32 string format is invalid. - private static byte[] Decode(ReadOnlySpan value, string alphabet, bool padding) + public static byte[] Decode(ReadOnlySpan value, string alphabet, bool padding) { - if (value == string.Empty) - { - return Array.Empty(); - } + if (value == string.Empty) return []; if (padding && value.Length % InputSize != 0) - { throw new FormatException("Base32 string is invalid. Insufficient padding has been applied."); - } ReadOnlySpan valueWithoutPadding = padding ? value.TrimEnd('=') : value; byte[] outputBytes = new byte[valueWithoutPadding.Length * OutputSize / InputSize]; if (outputBytes.Length == 0) - { throw new FormatException("Base32 string is invalid. Not enough data to construct byte array."); - } int inputPosition = 0; int inputSubPosition = 0; @@ -127,9 +118,7 @@ private static byte[] Decode(ReadOnlySpan value, string alphabet, bool pad int index = alphabet.IndexOf(character); if (index < 0) - { throw new FormatException($"Invalid Base32 character '{character}' at position {inputPosition}"); - } int availableBits = Math.Min(OutputSize - inputSubPosition, InputSize - outputSubPosition); diff --git a/OnixLabs.Core/Text/Base32FormatInfo.cs b/OnixLabs.Core/Text/Base32FormatInfo.cs new file mode 100644 index 0000000..7b8eac9 --- /dev/null +++ b/OnixLabs.Core/Text/Base32FormatInfo.cs @@ -0,0 +1,80 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +/// +/// Represents Base-32 formatting information. +/// +public sealed class Base32FormatInfo : IFormatProvider +{ + /// + /// The default (RFC-4648) Base-32 alphabet. + /// + public static Base32FormatInfo Default => new(nameof(Default), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); + + /// + /// The Z-Base-32 alphabet. + /// + public static Base32FormatInfo ZBase32 => new(nameof(ZBase32), "ybndrfg8ejkmcpqxot1uwisza345h769"); + + /// + /// The Geohash Base-32 alphabet. + /// + public static Base32FormatInfo GeoHash => new(nameof(GeoHash), "0123456789bcdefghjkmnpqrstuvwxyz"); + + /// + /// The Crockford Base-32 alphabet. + /// + public static Base32FormatInfo Crockford => new(nameof(Crockford), "0123456789ABCDEFGHJKMNPQRSTVWXYZ"); + + /// + /// The Base-32 Hex alphabet. + /// + public static Base32FormatInfo Base32Hex => new(nameof(Base32Hex), "0123456789ABCDEFGHIJKLMNOPQRSTUV"); + + /// + /// Initializes a new instance of the class. + /// + /// The name of the Base-32 alphabet. + /// The alphabet that will be used for Base-32 encoding and decoding operations. + private Base32FormatInfo(string name, string alphabet) + { + Name = name; + Alphabet = alphabet; + } + + /// + /// Gets the name of the Base-32 alphabet. + /// + public string Name { get; } + + /// + /// Gets the alphabet that will be used for Base-32 encoding and decoding operations. + /// + public string Alphabet { get; } + + /// Returns an object that provides formatting services for the specified type. + /// An object that specifies the type of format object to return. + /// + /// Returns an instance of the object specified by , + /// if the implementation can supply that type of object; otherwise, . + /// + public object? GetFormat(Type? formatType) + { + return formatType == typeof(Base32FormatInfo) ? this : null; + } +} diff --git a/OnixLabs.Core/Text/Base58.Checksum.cs b/OnixLabs.Core/Text/Base58.Checksum.cs index 1529de9..aae55c4 100644 --- a/OnixLabs.Core/Text/Base58.Checksum.cs +++ b/OnixLabs.Core/Text/Base58.Checksum.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,6 +15,7 @@ using System; using System.Linq; using System.Security.Cryptography; +using System.Text; namespace OnixLabs.Core.Text; @@ -86,8 +87,6 @@ private static void VerifyChecksum(byte[] value) byte[] computedChecksum = ComputeChecksum(valueWithoutChecksum); if (!originalChecksum.SequenceEqual(computedChecksum)) - { throw new FormatException("Base-58 checksum is invalid."); - } } } diff --git a/OnixLabs.Core/Text/Base58.Constants.cs b/OnixLabs.Core/Text/Base58.Constants.cs index 7d07ef8..62b1ff7 100644 --- a/OnixLabs.Core/Text/Base58.Constants.cs +++ b/OnixLabs.Core/Text/Base58.Constants.cs @@ -1,18 +1,19 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core.Collections; +using System; +using System.Text; namespace OnixLabs.Core.Text; @@ -21,5 +22,5 @@ public readonly partial struct Base58 /// /// Gets an empty value. /// - public static Base58 Empty => Create(EmptyArray()); + public static Base58 Empty => new([]); } diff --git a/OnixLabs.Core/Text/Base58.Create.cs b/OnixLabs.Core/Text/Base58.Create.cs index 3d18ed1..65a6ee3 100644 --- a/OnixLabs.Core/Text/Base58.Create.cs +++ b/OnixLabs.Core/Text/Base58.Create.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,69 +20,85 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base58 { /// - /// Creates a instance from the specified array. + /// Creates a new value from the specified value. /// - /// The underlying value. - /// Returns a new instance. + /// The value from which to create a new value. + /// Returns a new value from the specified value. public static Base58 Create(byte[] value) { - return Create(value, Base58Alphabet.Default); + return new Base58(value); } /// - /// Creates a instance from the specified array. + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 Create(byte[] value, Base58Alphabet alphabet) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base58 Create(ReadOnlySpan value) { - return new Base58(value, alphabet); + return Create(value.ToArray()); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value, using the default . /// - /// The underlying value. - /// Returns a new instance. - public static Base58 Create(ReadOnlySpan value) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base58 Create(string value) { - return Create(value, Encoding.Default, Base58Alphabet.Default); + return Create(value.ToCharArray(), Encoding.Default); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. - public static Base58 Create(ReadOnlySpan value, Encoding encoding) + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base58 Create(string value, Encoding encoding) + { + return Create(value.ToCharArray(), encoding); + } + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base58 Create(char[] value) { - return Create(value, encoding, Base58Alphabet.Default); + return Create(value, Encoding.Default); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 Create(ReadOnlySpan value, Base58Alphabet alphabet) + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base58 Create(char[] value, Encoding encoding) { - return Create(value, Encoding.Default, alphabet); + return Create(encoding.GetBytes(value)); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value, using the default . /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// Returns a new instance. - public static Base58 Create(ReadOnlySpan value, Encoding encoding, Base58Alphabet alphabet) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base58 Create(ReadOnlySpan value) + { + return Create(value.ToArray(), Encoding.Default); + } + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base58 Create(ReadOnlySpan value, Encoding encoding) { - // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. - byte[] bytes = encoding.GetBytes(value.ToArray()); - return Create(bytes, alphabet); + return Create(value.ToArray(), encoding); } } diff --git a/OnixLabs.Core/Text/Base58.Equatable.cs b/OnixLabs.Core/Text/Base58.Equatable.cs index f327c23..24cd0b4 100644 --- a/OnixLabs.Core/Text/Base58.Equatable.cs +++ b/OnixLabs.Core/Text/Base58.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,6 +14,7 @@ using System; using System.Linq; +using System.Text; using OnixLabs.Core.Linq; namespace OnixLabs.Core.Text; @@ -27,7 +28,7 @@ public readonly partial struct Base58 /// Returns true if the object is equal to the current instance; otherwise, false. public bool Equals(Base58 other) { - return other.Value.SequenceEqual(Value) && other.Alphabet == Alphabet; + return value.SequenceEqual(other.value); } /// @@ -46,7 +47,7 @@ public override bool Equals(object? obj) /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(Value.GetContentHashCode()); + return HashCode.Combine(value.GetContentHashCode()); } /// diff --git a/OnixLabs.Core/Text/Base58.Format.cs b/OnixLabs.Core/Text/Base58.Format.cs new file mode 100644 index 0000000..0624fd7 --- /dev/null +++ b/OnixLabs.Core/Text/Base58.Format.cs @@ -0,0 +1,33 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +public readonly partial struct Base58 +{ + /// + /// Tries to format the value of the current instance into the provided span of characters. + /// + /// The span in which to write this instance's value formatted as a span of characters. + /// When this method returns, contains the number of characters that were written in . + /// A span containing the characters that represent a standard or custom format string that defines the acceptable format for . + /// An optional object that supplies culture-specific formatting information for . + /// Returns if the formatting was successful; otherwise, . + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + return ToString(format, provider).TryCopyTo(destination, out charsWritten); + } +} diff --git a/OnixLabs.Core/Text/Base58.Parse.cs b/OnixLabs.Core/Text/Base58.Parse.cs index 3044555..08f45c4 100644 --- a/OnixLabs.Core/Text/Base58.Parse.cs +++ b/OnixLabs.Core/Text/Base58.Parse.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,50 +19,134 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base58 { /// - /// Parses a Base-58 value into a instance. + /// Parses a Base-58 value into a value. /// - /// The Base-16 (hexadecimal) value to parse. + /// The Base-58 value to parse. + /// An object that provides format-specific information about the specified value. /// Returns a new instance. - public static Base58 Parse(ReadOnlySpan value) + public static Base58 Parse(string value, IFormatProvider? provider = null) { - return Parse(value, Base58Alphabet.Default); + return Parse(value.AsSpan(), provider); } /// - /// Parses a Base-58 value into a instance. + /// Parses a Base-58 value into a value. /// - /// The Base-16 (hexadecimal) value to parse. - /// The alphabet that will be used for Base-58 encoding and decoding operations. + /// The Base-58 value to parse. + /// An object that provides format-specific information about the specified value. /// Returns a new instance. - public static Base58 Parse(ReadOnlySpan value, Base58Alphabet alphabet) + public static Base58 Parse(ReadOnlySpan value, IFormatProvider? provider = null) { - byte[] bytes = Decode(value, alphabet.Alphabet); - return Create(bytes, alphabet); + if (TryParse(value, provider, out Base58 result)) return result; + throw new FormatException($"The input string '{value}' was not in a correct format."); } /// - /// Parses a Base-58 value with a checksum into a instance. + /// Parses a Base-58 value with a checksum into a value. /// - /// The Base-16 (hexadecimal) value to ParseWithChecksum. - /// A new instance. - public static Base58 ParseWithChecksum(ReadOnlySpan value) + /// The Base-58 value to parse. + /// An object that provides format-specific information about the specified value. + /// Returns a new instance. + public static Base58 ParseWithChecksum(string value, IFormatProvider? provider = null) + { + return ParseWithChecksum(value.AsSpan(), provider); + } + + /// + /// Parses a Base-58 value with a checksum into a value. + /// + /// The Base-58 value to parse. + /// An object that provides format-specific information about the specified value. + /// Returns a new instance. + public static Base58 ParseWithChecksum(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryParseWithChecksum(value, provider, out Base58 result)) return result; + throw new FormatException($"The input string '{value}' was not in a correct format."); + } + + /// + /// Tries to parse the specified Base-58 value into a value. + /// + /// The Base-58 value to parse. + /// An object that provides format-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, IFormatProvider? provider, out Base58 result) + { + return TryParse(value.AsSpan(), provider, out result); + } + + /// + /// Tries to parse the specified Base-58 value into a value. + /// + /// The Base-58 value to parse. + /// An object that provides format-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base58 result) + { + try + { + Base58FormatInfo info = provider as Base58FormatInfo ?? Base58FormatInfo.Default; + byte[] bytes = Base58Codec.Decode(value, info.Alphabet); + result = Create(bytes); + return true; + } + catch + { + result = Empty; + return false; + } + } + + /// + /// Tries to parse the specified Base-58 value with a checksum into a value. + /// + /// The Base-58 value to parse. + /// An object that provides format-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParseWithChecksum(string? value, IFormatProvider? provider, out Base58 result) { - return ParseWithChecksum(value, Base58Alphabet.Default); + return TryParseWithChecksum(value.AsSpan(), provider, out result); } /// - /// Parses a Base-58 value with a checksum into a instance. + /// Tries to parse the specified Base-58 value with a checksum into a value. /// - /// The Base-16 (hexadecimal) value to ParseWithChecksum. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - /// A new instance. - public static Base58 ParseWithChecksum(ReadOnlySpan value, Base58Alphabet alphabet) + /// The Base-58 value to parse. + /// An object that provides format-specific information about the specified value. + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParseWithChecksum(ReadOnlySpan value, IFormatProvider? provider, out Base58 result) { - byte[] bytes = Decode(value, alphabet.Alphabet); - byte[] bytesWithoutChecksum = RemoveChecksum(bytes); + try + { + Base58FormatInfo info = provider as Base58FormatInfo ?? Base58FormatInfo.Default; + byte[] bytes = Base58Codec.Decode(value, info.Alphabet); + byte[] bytesWithoutChecksum = RemoveChecksum(bytes); - VerifyChecksum(bytes); + VerifyChecksum(bytes); - return Create(bytesWithoutChecksum, alphabet); + result = Create(bytesWithoutChecksum); + return true; + } + catch + { + result = Empty; + return false; + } } } diff --git a/OnixLabs.Core/Text/Base58.To.cs b/OnixLabs.Core/Text/Base58.To.cs index 7add2f8..4d0c096 100644 --- a/OnixLabs.Core/Text/Base58.To.cs +++ b/OnixLabs.Core/Text/Base58.To.cs @@ -1,17 +1,18 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Text; namespace OnixLabs.Core.Text; @@ -24,45 +25,57 @@ public readonly partial struct Base58 /// Returns a array that represents the current object. public byte[] ToByteArray() { - return Value.Copy(); + return value.Copy(); } /// - /// Returns a that represents the current object, with a checksum. + /// Gets the plain-text representation of the current value, using the default . /// - /// Returns a that represents the current object, with a checksum. - public string ToStringWithChecksum() + /// Returns the plain-text representation of the current value, using the default . + public string ToPlainTextString() { - byte[] valueWithChecksum = AddChecksum(Value); - return Encode(valueWithChecksum, Alphabet.Alphabet); + return ToPlainTextString(Encoding.Default); } /// - /// Returns a that represents the current object in plain text. + /// Gets the plain-text representation of the current value. /// - /// Returns a that represents the current object in plain text. - public string ToPlainTextString() + /// The which will be used to obtain a from the current value. + /// Returns the plain-text representation of the current value. + public string ToPlainTextString(Encoding encoding) { - return ToPlainTextString(Encoding.Default); + return encoding.GetString(value); } /// - /// Returns a that represents the current object in plain text. + /// Returns a that represents the current object. /// - /// The encoding to use to obtain the underlying value. - /// Returns a that represents the current object in plain text. - public string ToPlainTextString(Encoding encoding) + /// Returns a that represents the current object. + public override string ToString() { - return encoding.GetString(Value); + return ToString(null); } + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(string? format, IFormatProvider? formatProvider = null) + { + return ToString(format.AsSpan(), formatProvider); + } /// - /// Returns a that represents the current object. + /// Formats the value of the current instance using the specified format. /// - /// A that represents the current object. - public override string ToString() + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) { - return Encode(Value, Alphabet.Alphabet); + Base58FormatInfo info = formatProvider as Base58FormatInfo ?? Base58FormatInfo.Default; + return Base58Codec.Encode(value, info.Alphabet); } } diff --git a/OnixLabs.Core/Text/Base58.cs b/OnixLabs.Core/Text/Base58.cs index f01c1f3..531931f 100644 --- a/OnixLabs.Core/Text/Base58.cs +++ b/OnixLabs.Core/Text/Base58.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,26 +17,19 @@ namespace OnixLabs.Core.Text; /// /// Represents a Base-58 value. /// -public readonly partial struct Base58 : IBase +public readonly partial struct Base58 : IBaseRepresentation { + /// + /// The underlying value. + /// + private readonly byte[] value; + /// /// Initializes a new instance of the struct. /// /// The underlying value. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - private Base58(byte[] value, Base58Alphabet alphabet) + private Base58(byte[] value) { - Value = value.Copy(); - Alphabet = alphabet; + this.value = value.Copy(); } - - /// - /// Gets the underlying value. - /// - private byte[] Value { get; } - - /// - /// Gets the alphabet that will be used for Base-58 encoding and decoding operations. - /// - private Base58Alphabet Alphabet { get; } } diff --git a/OnixLabs.Core/Text/Base58Alphabet.cs b/OnixLabs.Core/Text/Base58Alphabet.cs deleted file mode 100644 index 290f278..0000000 --- a/OnixLabs.Core/Text/Base58Alphabet.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Core.Text; - -/// -/// Specifies the supported Base-58 alphabets. -/// -public sealed class Base58Alphabet : Enumeration -{ - /// - /// The default Base-58 alphabet, which is the same as Bitcoin's Base-58 alphabet. - /// - public static Base58Alphabet Default => new(0, nameof(Default), "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"); - - /// - /// The Ripple Base-58 alphabet. - /// - public static Base58Alphabet Ripple => new(0, nameof(Ripple), "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"); - - /// - /// The Flickr Base-58 alphabet. - /// - public static Base58Alphabet Flickr => new(0, nameof(Flickr), "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"); - - /// - /// Initializes a new instance of the class. - /// - /// The value of the enumeration entry. - /// The name of the enumeration entry. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - private Base58Alphabet(int value, string name, string alphabet) : base(value, name) - { - Alphabet = alphabet; - } - - /// - /// Gets the alphabet that will be used for Base-58 encoding and decoding operations. - /// - public string Alphabet { get; } -} diff --git a/OnixLabs.Core/Text/Base58.Codec.cs b/OnixLabs.Core/Text/Base58Codec.cs similarity index 88% rename from OnixLabs.Core/Text/Base58.Codec.cs rename to OnixLabs.Core/Text/Base58Codec.cs index a7ecea7..0e9a34c 100644 --- a/OnixLabs.Core/Text/Base58.Codec.cs +++ b/OnixLabs.Core/Text/Base58Codec.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,7 +20,10 @@ namespace OnixLabs.Core.Text; -public readonly partial struct Base58 +/// +/// Represents a Base-58 encoder/decoder. +/// +internal static class Base58Codec { /// /// Encode a byte array into a Base-58 string. @@ -28,7 +31,7 @@ public readonly partial struct Base58 /// The value to encode. /// The Base-58 alphabet to use for encoding. /// Returns a Base-58 encoded string. - private static string Encode(byte[] value, string alphabet) + public static string Encode(IReadOnlyList value, string alphabet) { BigInteger data = value.Aggregate(BigInteger.Zero, (a, b) => a * 256 + b); StringBuilder result = new(); @@ -40,22 +43,19 @@ private static string Encode(byte[] value, string alphabet) result.Insert(0, alphabet[(int)remainder]); } - for (int index = 0; index < value.Length && value[index] == 0; index++) - { - result.Insert(0, '1'); - } + for (int index = 0; index < value.Count && value[index] == 0; index++) result.Insert(0, '1'); return result.ToString(); } /// - /// Decodes a Base-58 into a byte array. + /// Decodes a Base-58 into a byte array. /// /// The value to decode. /// The Base-58 alphabet to use for decoding. /// Returns a byte array. /// If the Base-58 string format is invalid. - private static byte[] Decode(ReadOnlySpan value, string alphabet) + public static byte[] Decode(ReadOnlySpan value, string alphabet) { BigInteger data = BigInteger.Zero; @@ -65,9 +65,7 @@ private static byte[] Decode(ReadOnlySpan value, string alphabet) int characterIndex = alphabet.IndexOf(character); if (characterIndex < 0) - { throw new FormatException($"Invalid Base58 character '{character}' at position {index}"); - } data = data * 58 + characterIndex; } diff --git a/OnixLabs.Core/Text/Base58FormatInfo.cs b/OnixLabs.Core/Text/Base58FormatInfo.cs new file mode 100644 index 0000000..344d66e --- /dev/null +++ b/OnixLabs.Core/Text/Base58FormatInfo.cs @@ -0,0 +1,67 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +/// +/// Represents Base-58 formatting information. +/// +public sealed class Base58FormatInfo : IFormatProvider +{ + /// + /// The default Base-58 alphabet, which is the same as Bitcoin's Base-58 alphabet. + /// + public static Base58FormatInfo Default => new(nameof(Default), "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"); + + /// + /// The Ripple Base-58 alphabet. + /// + public static Base58FormatInfo Ripple => new(nameof(Ripple), "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"); + + /// + /// The Flickr Base-58 alphabet. + /// + public static Base58FormatInfo Flickr => new(nameof(Flickr), "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"); + + /// + /// Initializes a new instance of the class. + /// + /// The name of the Base-58 alphabet. + /// The alphabet that will be used for Base-58 encoding and decoding operations. + private Base58FormatInfo(string name, string alphabet) + { + Name = name; + Alphabet = alphabet; + } + + /// + /// Gets the name of the Base-58 alphabet. + /// + public string Name { get; } + + /// + /// Gets the alphabet that will be used for Base-58 encoding and decoding operations. + /// + public string Alphabet { get; } + + /// Returns an object that provides formatting services for the specified type. + /// An object that specifies the type of format object to return. + /// An instance of the object specified by , if the implementation can supply that type of object; otherwise, . + public object? GetFormat(Type? formatType) + { + return formatType == typeof(Base58FormatInfo) ? this : null; + } +} diff --git a/OnixLabs.Core/Text/Base64.Constants.cs b/OnixLabs.Core/Text/Base64.Constants.cs index 0809bd8..bd35494 100644 --- a/OnixLabs.Core/Text/Base64.Constants.cs +++ b/OnixLabs.Core/Text/Base64.Constants.cs @@ -1,18 +1,19 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core.Collections; +using System; +using System.Text; namespace OnixLabs.Core.Text; @@ -21,5 +22,5 @@ public readonly partial struct Base64 /// /// Gets an empty value. /// - public static Base64 Empty => Create(EmptyArray()); + public static Base64 Empty => new([]); } diff --git a/OnixLabs.Core/Text/Base64.Create.cs b/OnixLabs.Core/Text/Base64.Create.cs index 3e605f1..43fac8b 100644 --- a/OnixLabs.Core/Text/Base64.Create.cs +++ b/OnixLabs.Core/Text/Base64.Create.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,35 +20,85 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base64 { /// - /// Creates a instance from the specified array. + /// Creates a new value from the specified value. /// - /// The underlying value. - /// Returns a new instance. + /// The value from which to create a new value. + /// Returns a new value from the specified value. public static Base64 Create(byte[] value) { return new Base64(value); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value. /// - /// The underlying value. - /// Returns a new instance. - public static Base64 Create(ReadOnlySpan value) + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base64 Create(ReadOnlySpan value) + { + return Create(value.ToArray()); + } + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base64 Create(string value) + { + return Create(value.ToCharArray(), Encoding.Default); + } + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base64 Create(string value, Encoding encoding) + { + return Create(value.ToCharArray(), encoding); + } + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base64 Create(char[] value) { return Create(value, Encoding.Default); } /// - /// Creates a instance from the specified . + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static Base64 Create(char[] value, Encoding encoding) + { + return Create(encoding.GetBytes(value)); + } + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static Base64 Create(ReadOnlySpan value) + { + return Create(value.ToArray(), Encoding.Default); + } + + /// + /// Creates a new value from the specified value. /// - /// The underlying value. - /// The encoding to use to obtain the underlying value. - /// Returns a new instance. + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. public static Base64 Create(ReadOnlySpan value, Encoding encoding) { - // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. - byte[] bytes = encoding.GetBytes(value.ToArray()); - return Create(bytes); + return Create(value.ToArray(), encoding); } } diff --git a/OnixLabs.Core/Text/Base64.Equatable.cs b/OnixLabs.Core/Text/Base64.Equatable.cs index cfedb91..1edf6c3 100644 --- a/OnixLabs.Core/Text/Base64.Equatable.cs +++ b/OnixLabs.Core/Text/Base64.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -27,7 +27,7 @@ public readonly partial struct Base64 /// Returns true if the object is equal to the current instance; otherwise, false. public bool Equals(Base64 other) { - return other.Value.SequenceEqual(Value); + return value.SequenceEqual(other.value); } /// @@ -46,7 +46,7 @@ public override bool Equals(object? obj) /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(Value.GetContentHashCode()); + return HashCode.Combine(value.GetContentHashCode()); } /// @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// Returns true if the instances are equal; otherwise, false. public static bool operator ==(Base64 left, Base64 right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// Returns true if the instances are not equal; otherwise, false. public static bool operator !=(Base64 left, Base64 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base64.Format.cs b/OnixLabs.Core/Text/Base64.Format.cs new file mode 100644 index 0000000..4756003 --- /dev/null +++ b/OnixLabs.Core/Text/Base64.Format.cs @@ -0,0 +1,33 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +public readonly partial struct Base64 +{ + /// + /// Tries to format the value of the current instance into the provided span of characters. + /// + /// The span in which to write this instance's value formatted as a span of characters. + /// When this method returns, contains the number of characters that were written in . + /// A span containing the characters that represent a standard or custom format string that defines the acceptable format for . + /// An optional object that supplies culture-specific formatting information for . + /// Returns if the formatting was successful; otherwise, . + bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) + { + return ToString(format, provider).TryCopyTo(destination, out charsWritten); + } +} diff --git a/OnixLabs.Core/Text/Base64.Parse.cs b/OnixLabs.Core/Text/Base64.Parse.cs index 10c1512..7225916 100644 --- a/OnixLabs.Core/Text/Base64.Parse.cs +++ b/OnixLabs.Core/Text/Base64.Parse.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,13 +19,77 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base64 { /// - /// Parses a Base-64 value into a instance. + /// Parses a Base-64 value into a value. /// - /// The Base-16 (hexadecimal) value to parse. + /// The Base-64 value to parse. + /// + /// An object that provides format-specific information about the specified value. + /// The parameter is ignored by the current implementation of . + /// /// Returns a new instance. - public static Base64 Parse(ReadOnlySpan value) + public static Base64 Parse(string value, IFormatProvider? provider = null) { - byte[] bytes = Convert.FromBase64String(value.ToString()); - return Create(bytes); + return Parse(value.AsSpan(), provider); + } + + /// + /// Parses a Base-64 value into a value. + /// + /// The Base-64 value to parse. + /// + /// An object that provides format-specific information about the specified value. + /// The parameter is ignored by the current implementation of . + /// + /// Returns a new instance. + public static Base64 Parse(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryParse(value, provider, out Base64 result)) return result; + throw new FormatException($"The input string '{value}' was not in a correct format."); + } + + /// + /// Tries to parse the specified Base-64 value into a value. + /// + /// The Base-64 value to parse. + /// + /// An object that provides format-specific information about the specified value. + /// The parameter is ignored by the current implementation of . + /// + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(string? value, IFormatProvider? provider, out Base64 result) + { + return TryParse(value.AsSpan(), provider, out result); + } + + /// + /// Tries to parse the specified Base-64 value into a value. + /// + /// The Base-64 value to parse. + /// + /// An object that provides format-specific information about the specified value. + /// The parameter is ignored by the current implementation of . + /// + /// + /// On return, contains the result of parsing the specified value, + /// or the default value in the event that the specified value could not be parsed. + /// + /// Returns true if the specified value was parsed successfully; otherwise, false. + public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base64 result) + { + try + { + byte[] bytes = Convert.FromBase64String(value.ToString()); + result = Create(bytes); + return true; + } + catch + { + result = Empty; + return false; + } } } diff --git a/OnixLabs.Core/Text/Base64.To.cs b/OnixLabs.Core/Text/Base64.To.cs index 2386b73..31fb122 100644 --- a/OnixLabs.Core/Text/Base64.To.cs +++ b/OnixLabs.Core/Text/Base64.To.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -25,26 +25,26 @@ public readonly partial struct Base64 /// Returns a array that represents the current object. public byte[] ToByteArray() { - return Value.Copy(); + return value.Copy(); } /// - /// Returns a that represents the current object in plain text. + /// Gets the plain-text representation of the current value, using the default . /// - /// Returns a that represents the current object in plain text. + /// Returns the plain-text representation of the current value, using the default . public string ToPlainTextString() { return ToPlainTextString(Encoding.Default); } /// - /// Returns a that represents the current object in plain text. + /// Gets the plain-text representation of the current value. /// - /// The encoding to use to obtain the underlying value. - /// Returns a that represents the current object in plain text. + /// The which will be used to obtain a from the current value. + /// Returns the plain-text representation of the current value. public string ToPlainTextString(Encoding encoding) { - return encoding.GetString(Value); + return encoding.GetString(value); } /// @@ -53,6 +53,28 @@ public string ToPlainTextString(Encoding encoding) /// Returns a that represents the current object. public override string ToString() { - return Convert.ToBase64String(Value); + return ToString(null); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(string? format, IFormatProvider? formatProvider = null) + { + return ToString(format.AsSpan(), formatProvider); + } + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use, or null to use the default format. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + { + return Convert.ToBase64String(value); } } diff --git a/OnixLabs.Core/Text/Base64.cs b/OnixLabs.Core/Text/Base64.cs index 0bb0960..d4a4ef4 100644 --- a/OnixLabs.Core/Text/Base64.cs +++ b/OnixLabs.Core/Text/Base64.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,19 +17,19 @@ namespace OnixLabs.Core.Text; /// /// Represents a Base-64 value. /// -public readonly partial struct Base64 : IBase +public readonly partial struct Base64 : IBaseRepresentation { + /// + /// The underlying value. + /// + private readonly byte[] value; + /// /// Initializes a new instance of the struct. /// /// The underlying value. private Base64(byte[] value) { - Value = value.Copy(); + this.value = value.Copy(); } - - /// - /// Gets the underlying value. - /// - private byte[] Value { get; } } diff --git a/OnixLabs.Core/Text/IBase.cs b/OnixLabs.Core/Text/IBase.cs deleted file mode 100644 index 62a6336..0000000 --- a/OnixLabs.Core/Text/IBase.cs +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Text; - -namespace OnixLabs.Core.Text; - -/// -/// Represents a number base representation. -/// -/// The underlying type of the number base representation. -public interface IBase : IEquatable where TSelf : struct, IBase -{ - /// - /// Gets an empty value. - /// - public static virtual TSelf Empty => TSelf.Create(EmptyArray()); - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(byte[] value); - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static virtual TSelf Create(ReadOnlySpan value) - { - return TSelf.Create(value, Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The from which to obtain a value. - /// Returns a new value from the specified value. - public static virtual TSelf Create(ReadOnlySpan value, Encoding encoding) - { - // TODO : Check if future versions support GetBytes with ReadOnlySpan overload. - byte[] bytes = encoding.GetBytes(value.ToArray()); - return TSelf.Create(bytes); - } - - /// - /// Parses a value from the specified value. - /// - /// The value from which to parse a value. - /// Returns a new value parsed from the specified value. - public static abstract TSelf Parse(ReadOnlySpan value); - - /// - /// Gets the current as a value. - /// - /// Returns the current as a value. - byte[] ToByteArray(); - - /// - /// Gets the plain-text representation of the current value. - /// - /// Returns the plain-text representation of the current value. - public string ToPlainTextString() - { - return ToPlainTextString(Encoding.Default); - } - - /// - /// Gets the plain-text representation of the current value. - /// - /// The from which to obtain a value. - /// Returns the plain-text representation of the current value. - public string ToPlainTextString(Encoding encoding) - { - byte[] bytes = ToByteArray(); - return encoding.GetString(bytes); - } -} diff --git a/OnixLabs.Core/Text/IBaseRepresentation.cs b/OnixLabs.Core/Text/IBaseRepresentation.cs new file mode 100644 index 0000000..4094554 --- /dev/null +++ b/OnixLabs.Core/Text/IBaseRepresentation.cs @@ -0,0 +1,136 @@ +// Copyright © 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Text; + +namespace OnixLabs.Core.Text; + +/// +/// Defines a number base representation. +/// +/// The underlying type of the number base representation. +public interface IBaseRepresentation : + IEquatable, + ISpanParsable, + ISpanFormattable + where TSelf : struct, IBaseRepresentation +{ + /// + /// Gets an empty value. + /// + public static abstract TSelf Empty { get; } + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(byte[] value); + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(ReadOnlySpan value); + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(string value); + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(string value, Encoding encoding); + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(char[] value); + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(char[] value, Encoding encoding); + + /// + /// Creates a new value from the specified value, using the default . + /// + /// The value from which to create a new value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(ReadOnlySpan value); + + /// + /// Creates a new value from the specified value. + /// + /// The value from which to create a new value. + /// The which will be used to obtain a from the specified value. + /// Returns a new value from the specified value. + public static abstract TSelf Create(ReadOnlySpan value, Encoding encoding); + + /// + /// Performs an equality check between two instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the instances are equal; otherwise, . + public static abstract bool operator ==(TSelf left, TSelf right); + + /// + /// Performs an inequality check between two instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the instances are not equal; otherwise, . + public static abstract bool operator !=(TSelf left, TSelf right); + + /// + /// Gets the underlying represented by the current value. + /// + /// Returns the underlying represented by the current value. + public byte[] ToByteArray(); + + /// + /// Gets the plain-text representation of the current value, using the default . + /// + /// Returns the plain-text representation of the current value, using the default . + public string ToPlainTextString(); + + /// + /// Gets the plain-text representation of the current value. + /// + /// The which will be used to obtain a from the current value. + /// Returns the plain-text representation of the current value. + public string ToPlainTextString(Encoding encoding); + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider); +} diff --git a/OnixLabs.Numerics/BigDecimal.Format.cs b/OnixLabs.Numerics/BigDecimal.Format.cs index 1d67893..9d7ea0d 100644 --- a/OnixLabs.Numerics/BigDecimal.Format.cs +++ b/OnixLabs.Numerics/BigDecimal.Format.cs @@ -13,7 +13,6 @@ // limitations under the License. using System; -using System.Globalization; namespace OnixLabs.Numerics; @@ -29,8 +28,7 @@ public readonly partial struct BigDecimal /// Returns if the formatting was successful; otherwise, . bool ISpanFormattable.TryFormat(Span destination, out int charsWritten, ReadOnlySpan format, IFormatProvider? provider) { - CultureInfo info = provider as CultureInfo ?? DefaultCulture; - string formatted = ToString(format, info); + string formatted = ToString(format, provider); if (formatted.Length > destination.Length) { diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs index a993c91..db89849 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,17 +44,7 @@ public Base16 ToBase16() /// Returns a value that represents the underlying signature data. public Base32 ToBase32() { - return ToBase32(Base32Alphabet.Default); - } - - /// - /// Returns a value that represents the underlying signature data. - /// - /// The Base-32 alphabet to use to encode the signature data. - /// Returns a value that represents the underlying signature data. - public Base32 ToBase32(Base32Alphabet alphabet) - { - return Base32.Create(Value, alphabet); + return Base32.Create(Value); } /// @@ -63,17 +53,7 @@ public Base32 ToBase32(Base32Alphabet alphabet) /// Returns a value that represents the underlying signature data. public Base58 ToBase58() { - return ToBase58(Base58Alphabet.Default); - } - - /// - /// Returns a value that represents the underlying signature data. - /// - /// The Base-58 alphabet to use to encode the signature data. - /// Returns a value that represents the underlying signature data. - public Base58 ToBase58(Base58Alphabet alphabet) - { - return Base58.Create(Value, alphabet); + return Base58.Create(Value); } /// diff --git a/OnixLabs.Security.Cryptography/Hash.To.cs b/OnixLabs.Security.Cryptography/Hash.To.cs index 9f54df6..3513180 100644 --- a/OnixLabs.Security.Cryptography/Hash.To.cs +++ b/OnixLabs.Security.Cryptography/Hash.To.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,17 +44,7 @@ public Base16 ToBase16() /// Returns a value that represents the underlying hash data. public Base32 ToBase32() { - return ToBase32(Base32Alphabet.Default); - } - - /// - /// Returns a value that represents the underlying hash data. - /// - /// The Base-32 alphabet to use to encode the hash data. - /// Returns a value that represents the underlying hash data. - public Base32 ToBase32(Base32Alphabet alphabet) - { - return Base32.Create(Value, alphabet); + return Base32.Create(Value); } /// @@ -63,17 +53,7 @@ public Base32 ToBase32(Base32Alphabet alphabet) /// Returns a value that represents the underlying hash data. public Base58 ToBase58() { - return ToBase58(Base58Alphabet.Default); - } - - /// - /// Returns a value that represents the underlying hash data. - /// - /// The Base-58 alphabet to use to encode the hash data. - /// Returns a value that represents the underlying hash data. - public Base58 ToBase58(Base58Alphabet alphabet) - { - return Base58.Create(Value, alphabet); + return Base58.Create(Value); } /// diff --git a/OnixLabs.Security.Cryptography/PrivateKey.To.cs b/OnixLabs.Security.Cryptography/PrivateKey.To.cs index 51cdb96..42ac696 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.To.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.To.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,17 +44,7 @@ public Base16 ToBase16() /// Returns a value that represents the underlying private key data. public Base32 ToBase32() { - return ToBase32(Base32Alphabet.Default); - } - - /// - /// Returns a value that represents the underlying private key data. - /// - /// The Base-32 alphabet to use to encode the private key data. - /// Returns a value that represents the underlying private key data. - public Base32 ToBase32(Base32Alphabet alphabet) - { - return Base32.Create(KeyData, alphabet); + return Base32.Create(KeyData); } /// @@ -63,17 +53,7 @@ public Base32 ToBase32(Base32Alphabet alphabet) /// Returns a value that represents the underlying private key data. public Base58 ToBase58() { - return ToBase58(Base58Alphabet.Default); - } - - /// - /// Returns a value that represents the underlying private key data. - /// - /// The Base-58 alphabet to use to encode the private key data. - /// Returns a value that represents the underlying private key data. - public Base58 ToBase58(Base58Alphabet alphabet) - { - return Base58.Create(KeyData, alphabet); + return Base58.Create(KeyData); } /// diff --git a/OnixLabs.Security.Cryptography/PublicKey.To.cs b/OnixLabs.Security.Cryptography/PublicKey.To.cs index c3bacf7..fb3bf45 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.To.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.To.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,17 +44,7 @@ public Base16 ToBase16() /// Returns a value that represents the underlying public key data. public Base32 ToBase32() { - return ToBase32(Base32Alphabet.Default); - } - - /// - /// Returns a value that represents the underlying public key data. - /// - /// The Base-32 alphabet to use to encode the public key data. - /// Returns a value that represents the underlying public key data. - public Base32 ToBase32(Base32Alphabet alphabet) - { - return Base32.Create(KeyData, alphabet); + return Base32.Create(KeyData); } /// @@ -63,17 +53,7 @@ public Base32 ToBase32(Base32Alphabet alphabet) /// Returns a value that represents the underlying public key data. public Base58 ToBase58() { - return ToBase58(Base58Alphabet.Default); - } - - /// - /// Returns a value that represents the underlying public key data. - /// - /// The Base-58 alphabet to use to encode the public key data. - /// Returns a value that represents the underlying public key data. - public Base58 ToBase58(Base58Alphabet alphabet) - { - return Base58.Create(KeyData, alphabet); + return Base58.Create(KeyData); } /// diff --git a/onixlabs-dotnet.sln.DotSettings b/onixlabs-dotnet.sln.DotSettings index 70035ef..be92f32 100644 --- a/onixlabs-dotnet.sln.DotSettings +++ b/onixlabs-dotnet.sln.DotSettings @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. True + True True True True From b12ebbec31163f1ea7300de76ecf16736adaaf47 Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Sat, 6 Apr 2024 01:16:06 +0100 Subject: [PATCH 11/14] update/cleanup (#36) General code cleanup --- .../Collections/CollectionTests.cs | 91 ++++++-------- OnixLabs.Core/Collections/Collection.Empty.cs | 87 +++----------- OnixLabs.Core/Collections/Collection.Of.cs | 111 ++++-------------- OnixLabs.Core/Enumeration.Comparable.cs | 8 +- OnixLabs.Core/Enumeration.Equatable.cs | 16 +-- OnixLabs.Core/Enumeration.cs | 10 +- OnixLabs.Core/Linq/Extensions.IEnumerable.cs | 16 +-- OnixLabs.Core/Preconditions.cs | 5 +- OnixLabs.Core/Text/Base16.Equatable.cs | 8 +- OnixLabs.Core/Text/Base16.Parse.cs | 4 +- OnixLabs.Core/Text/Base32.Equatable.cs | 8 +- OnixLabs.Core/Text/Base32.Parse.cs | 4 +- OnixLabs.Core/Text/Base58.Equatable.cs | 8 +- OnixLabs.Core/Text/Base58.Parse.cs | 8 +- OnixLabs.Core/Text/Base64.Equatable.cs | 8 +- OnixLabs.Core/Text/Base64.Parse.cs | 4 +- OnixLabs.Numerics/BigDecimal.Comparable.cs | 8 +- OnixLabs.Numerics/BigDecimal.Convertible.cs | 2 +- OnixLabs.Numerics/BigDecimal.Equatable.cs | 16 +-- OnixLabs.Numerics/BigDecimal.Is.cs | 34 +++--- OnixLabs.Numerics/BigDecimal.Parse.cs | 12 +- OnixLabs.Numerics/BigDecimal.To.cs | 2 +- OnixLabs.Numerics/BigDecimal.cs | 3 +- OnixLabs.Numerics/Ieee754Converter.cs | 2 +- OnixLabs.Numerics/NumberInfo.Comparable.cs | 13 +- OnixLabs.Numerics/NumberInfo.Equatable.cs | 18 +-- OnixLabs.Numerics/NumberInfo.Parse.cs | 14 +-- OnixLabs.Numerics/NumberInfo.To.cs | 2 +- OnixLabs.Numerics/NumberInfo.cs | 9 +- OnixLabs.Numerics/NumericsExtensions.cs | 2 +- .../DigitalSignature.Equatable.cs | 14 +-- .../DigitalSignature.Validation.cs | 12 +- .../EcdsaPublicKey.Verify.cs | 10 +- .../Hash.Equatable.cs | 14 +-- OnixLabs.Security.Cryptography/Hash.Parse.cs | 10 +- .../HashAlgorithmType.Verify.cs | 8 +- .../Hmac.Equatable.cs | 14 +-- OnixLabs.Security.Cryptography/Hmac.Parse.cs | 8 +- OnixLabs.Security.Cryptography/Hmac.Verify.cs | 12 +- .../KeyPair.Equatable.cs | 14 +-- .../MerkleTree.Equatable.cs | 14 +-- .../MerkleTree.Generic.Equatable.cs | 14 +-- .../PrivateKey.Equatable.cs | 14 +-- .../PublicKey.Equatable.cs | 14 +-- .../PublicKey.Verify.cs | 18 +-- .../RsaPrivateKey.Equatable.cs | 8 +- .../RsaPublicKey.Equatable.cs | 8 +- .../RsaPublicKey.Verify.cs | 10 +- .../Salt.Equatable.cs | 14 +-- 49 files changed, 315 insertions(+), 448 deletions(-) diff --git a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs index 4b9ddf0..50a4d8b 100644 --- a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs +++ b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -45,187 +45,170 @@ public sealed class CollectionTests public void CollectionsEmptyEnumerableShouldProduceTheExpectedResult() { // Given - IEnumerable expected = Enumerable.Empty(); - IEnumerable actual = EmptyEnumerable(); + IEnumerable candidate = EmptyEnumerable(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyArray should produce the expected result")] public void CollectionsEmptyArrayShouldProduceTheExpectedResult() { // Given - object[] expected = Array.Empty(); - object[] actual = EmptyArray(); + object[] candidate = EmptyArray(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyImmutableArray should produce the expected result")] public void CollectionsEmptyImmutableArrayShouldProduceTheExpectedResult() { // Given - ImmutableArray expected = ImmutableArray.Create(); - ImmutableArray actual = EmptyImmutableArray(); + ImmutableArray candidate = EmptyImmutableArray(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyList should produce the expected result")] public void CollectionsEmptyListShouldProduceTheExpectedResult() { // Given - List expected = new(); - List actual = EmptyList(); + List candidate = EmptyList(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyImmutableList should produce the expected result")] public void CollectionsEmptyImmutableListShouldProduceTheExpectedResult() { // Given - ImmutableList expected = ImmutableList.Create(); - ImmutableList actual = EmptyImmutableList(); + ImmutableList candidate = EmptyImmutableList(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyDictionary should produce the expected result")] public void CollectionsEmptyDictionaryShouldProduceTheExpectedResult() { // Given - Dictionary expected = new(); - Dictionary actual = EmptyDictionary(); + Dictionary candidate = EmptyDictionary(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyImmutableDictionary should produce the expected result")] public void CollectionsEmptyImmutableDictionaryShouldProduceTheExpectedResult() { // Given - ImmutableDictionary expected = ImmutableDictionary.Create(); - ImmutableDictionary actual = EmptyImmutableDictionary(); + ImmutableDictionary candidate = EmptyImmutableDictionary(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptySortedDictionary should produce the expected result")] public void CollectionsEmptySortedDictionaryShouldProduceTheExpectedResult() { // Given - SortedDictionary expected = new(); - SortedDictionary actual = EmptySortedDictionary(); + SortedDictionary candidate = EmptySortedDictionary(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyImmutableSortedDictionary should produce the expected result")] public void CollectionsEmptyImmutableSortedDictionaryShouldProduceTheExpectedResult() { // Given - ImmutableSortedDictionary expected = ImmutableSortedDictionary.Create(); - ImmutableSortedDictionary actual = EmptyImmutableSortedDictionary(); + ImmutableSortedDictionary candidate = EmptyImmutableSortedDictionary(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyHashSet should produce the expected result")] public void CollectionsEmptyHashSetShouldProduceTheExpectedResult() { // Given - HashSet expected = new(); - HashSet actual = EmptyHashSet(); + HashSet candidate = EmptyHashSet(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyImmutableHashSet should produce the expected result")] public void CollectionsEmptyImmutableHashSetShouldProduceTheExpectedResult() { // Given - ImmutableHashSet expected = ImmutableHashSet.Create(); - ImmutableHashSet actual = EmptyImmutableHashSet(); + ImmutableHashSet candidate = EmptyImmutableHashSet(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptySortedSet should produce the expected result")] public void CollectionsEmptySortedSetShouldProduceTheExpectedResult() { // Given - SortedSet expected = new(); - SortedSet actual = EmptySortedSet(); + SortedSet candidate = EmptySortedSet(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyImmutableSortedSet should produce the expected result")] public void CollectionsEmptyImmutableSortedSetShouldProduceTheExpectedResult() { // Given - ImmutableSortedSet expected = ImmutableSortedSet.Create(); - ImmutableSortedSet actual = EmptyImmutableSortedSet(); + ImmutableSortedSet candidate = EmptyImmutableSortedSet(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyStack should produce the expected result")] public void CollectionsEmptyStackShouldProduceTheExpectedResult() { // Given - Stack expected = new(); - Stack actual = EmptyStack(); + Stack candidate = EmptyStack(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyImmutableStack should produce the expected result")] public void CollectionsEmptyImmutableStackShouldProduceTheExpectedResult() { // Given - ImmutableStack expected = ImmutableStack.Create(); - ImmutableStack actual = EmptyImmutableStack(); + ImmutableStack candidate = EmptyImmutableStack(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyQueue should produce the expected result")] public void CollectionsEmptyQueueShouldProduceTheExpectedResult() { // Given - Queue expected = new(); - Queue actual = EmptyQueue(); + Queue candidate = EmptyQueue(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EmptyImmutableQueue should produce the expected result")] public void CollectionsEmptyImmutableQueueShouldProduceTheExpectedResult() { // Given - ImmutableQueue expected = ImmutableQueue.Create(); - ImmutableQueue actual = EmptyImmutableQueue(); + ImmutableQueue candidate = EmptyImmutableQueue(); // Then - Assert.Equal(expected, actual); + Assert.Empty(candidate); } [Fact(DisplayName = "Collections.EnumerableOf should return the expected result")] diff --git a/OnixLabs.Core/Collections/Collection.Empty.cs b/OnixLabs.Core/Collections/Collection.Empty.cs index 8bc0146..53c8fce 100644 --- a/OnixLabs.Core/Collections/Collection.Empty.cs +++ b/OnixLabs.Core/Collections/Collection.Empty.cs @@ -12,10 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Collections.Generic; using System.Collections.Immutable; -using System.Linq; namespace OnixLabs.Core.Collections; @@ -29,50 +27,35 @@ public static partial class Collection /// /// The underlying type of the enumerable. /// Returns an empty enumerable. - public static IEnumerable EmptyEnumerable() - { - return Enumerable.Empty(); - } + public static IEnumerable EmptyEnumerable() => []; /// /// Creates an empty array. /// /// The underlying type of the array. /// Returns an empty array. - public static T[] EmptyArray() - { - return Array.Empty(); - } + public static T[] EmptyArray() => []; /// /// Creates an empty immutable array. /// /// The underlying type of the immutable array. /// Returns an empty immutable array. - public static ImmutableArray EmptyImmutableArray() - { - return ImmutableArray.Empty; - } + public static ImmutableArray EmptyImmutableArray() => []; /// /// Creates an empty list. /// /// The underlying type of the list. /// Returns an empty list. - public static List EmptyList() - { - return []; - } + public static List EmptyList() => []; /// /// Creates an empty immutable list. /// /// The underlying type of the immutable list. /// Returns an empty immutable list. - public static ImmutableList EmptyImmutableList() - { - return ImmutableList.Empty; - } + public static ImmutableList EmptyImmutableList() => []; /// /// Creates an empty dictionary. @@ -80,10 +63,7 @@ public static ImmutableList EmptyImmutableList() /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns an empty dictionary. - public static Dictionary EmptyDictionary() where TKey : notnull - { - return []; - } + public static Dictionary EmptyDictionary() where TKey : notnull => []; /// /// Creates an empty immutable dictionary. @@ -91,10 +71,7 @@ public static Dictionary EmptyDictionary() where TKe /// The underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an empty immutable dictionary. - public static ImmutableDictionary EmptyImmutableDictionary() where TKey : notnull - { - return ImmutableDictionary.Empty; - } + public static ImmutableDictionary EmptyImmutableDictionary() where TKey : notnull => ImmutableDictionary.Empty; /// /// Creates an empty sorted dictionary. @@ -102,10 +79,7 @@ public static ImmutableDictionary EmptyImmutableDictionaryThe underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns an empty sorted dictionary. - public static SortedDictionary EmptySortedDictionary() where TKey : notnull - { - return []; - } + public static SortedDictionary EmptySortedDictionary() where TKey : notnull => []; /// /// Creates an empty immutable sorted dictionary. @@ -113,88 +87,61 @@ public static SortedDictionary EmptySortedDictionary /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an empty immutable sorted dictionary. - public static ImmutableSortedDictionary EmptyImmutableSortedDictionary() where TKey : notnull - { - return ImmutableSortedDictionary.Empty; - } + public static ImmutableSortedDictionary EmptyImmutableSortedDictionary() where TKey : notnull => ImmutableSortedDictionary.Empty; /// /// Creates an empty hash set. /// /// The underlying type of the hash set. /// Returns an empty hash set. - public static HashSet EmptyHashSet() - { - return []; - } + public static HashSet EmptyHashSet() => []; /// /// Creates an empty immutable hash set. /// /// The underlying type of the immutable hash set. /// Returns an empty immutable hash set. - public static ImmutableHashSet EmptyImmutableHashSet() - { - return ImmutableHashSet.Empty; - } + public static ImmutableHashSet EmptyImmutableHashSet() => []; /// /// Creates an empty sorted set. /// /// The underlying type of the sorted set. /// Returns an empty sorted set. - public static SortedSet EmptySortedSet() - { - return []; - } + public static SortedSet EmptySortedSet() => []; /// /// Creates an empty immutable sorted set. /// /// The underlying type of the immutable sorted set. /// Returns an empty immutable sorted set. - public static ImmutableSortedSet EmptyImmutableSortedSet() - { - return ImmutableSortedSet.Empty; - } + public static ImmutableSortedSet EmptyImmutableSortedSet() => []; /// /// Creates an empty stack. /// /// The underlying type of the stack. /// Returns an empty stack. - public static Stack EmptyStack() - { - return []; - } + public static Stack EmptyStack() => []; /// /// Creates an empty immutable stack. /// /// The underlying type of the immutable stack. /// Returns an empty immutable stack. - public static ImmutableStack EmptyImmutableStack() - { - return ImmutableStack.Empty; - } + public static ImmutableStack EmptyImmutableStack() => []; /// /// Creates an empty queue. /// /// The underlying type of the queue. /// Returns an empty queue. - public static Queue EmptyQueue() - { - return []; - } + public static Queue EmptyQueue() => []; /// /// Creates an empty immutable queue. /// /// The underlying type of the immutable queue. /// Returns an empty immutable queue. - public static ImmutableQueue EmptyImmutableQueue() - { - return ImmutableQueue.Empty; - } + public static ImmutableQueue EmptyImmutableQueue() => []; } diff --git a/OnixLabs.Core/Collections/Collection.Of.cs b/OnixLabs.Core/Collections/Collection.Of.cs index 1d35a57..1710a4e 100644 --- a/OnixLabs.Core/Collections/Collection.Of.cs +++ b/OnixLabs.Core/Collections/Collection.Of.cs @@ -26,10 +26,7 @@ public static partial class Collection /// The items which will populate the enumerable. /// The underlying type of the enumerable. /// Returns an enumerable populated with the specified items. - public static IEnumerable EnumerableOf(params T[] items) - { - return [..items]; - } + public static IEnumerable EnumerableOf(params T[] items) => [..items]; /// /// Creates an array of the specified items. @@ -37,10 +34,7 @@ public static IEnumerable EnumerableOf(params T[] items) /// The items which will populate the array. /// The underlying type of the array. /// Returns an array populated with the specified items. - public static T[] ArrayOf(params T[] items) - { - return [..items]; - } + public static T[] ArrayOf(params T[] items) => [..items]; /// /// Creates an immutable array of the specified items. @@ -48,10 +42,7 @@ public static T[] ArrayOf(params T[] items) /// The items which will populate the immutable array. /// The underlying type of the immutable array. /// Returns an immutable array populated with the specified items. - public static ImmutableArray ImmutableArrayOf(params T[] items) - { - return [..items]; - } + public static ImmutableArray ImmutableArrayOf(params T[] items) => [..items]; /// /// Creates a list of the specified items. @@ -59,10 +50,7 @@ public static ImmutableArray ImmutableArrayOf(params T[] items) /// The items which will populate the list. /// The underlying type of the list. /// Returns a list populated with the specified items. - public static List ListOf(params T[] items) - { - return [..items]; - } + public static List ListOf(params T[] items) => [..items]; /// /// Creates an immutable list of the specified items. @@ -70,10 +58,7 @@ public static List ListOf(params T[] items) /// The items which will populate the immutable list. /// The underlying type of the immutable list. /// Returns an immutable list populated with the specified items. - public static ImmutableList ImmutableListOf(params T[] items) - { - return [..items]; - } + public static ImmutableList ImmutableListOf(params T[] items) => [..items]; /// /// Create a dictionary of the specified items. @@ -82,10 +67,7 @@ public static ImmutableList ImmutableListOf(params T[] items) /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns a dictionary populated with the specified items. - public static Dictionary DictionaryOf(params KeyValuePair[] items) where TKey : notnull - { - return new Dictionary(items); - } + public static Dictionary DictionaryOf(params KeyValuePair[] items) where TKey : notnull => new(items); /// /// Create a dictionary of the specified items. @@ -94,10 +76,7 @@ public static Dictionary DictionaryOf(params KeyValu /// The underlying type of the dictionary key. /// The underlying type of the dictionary value. /// Returns a dictionary populated with the specified items. - public static Dictionary DictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull - { - return DictionaryOf(items.Select(item => new KeyValuePair(item.key, item.value)).ToArray()); - } + public static Dictionary DictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull => DictionaryOf(items.Select(item => new KeyValuePair(item.key, item.value)).ToArray()); /// /// Create an immutable dictionary of the specified items. @@ -106,11 +85,7 @@ public static Dictionary DictionaryOf(params (TKey k /// The underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an immutable dictionary populated with the specified items. - public static ImmutableDictionary ImmutableDictionaryOf( - params KeyValuePair[] items) where TKey : notnull - { - return ImmutableDictionary.CreateRange(items); - } + public static ImmutableDictionary ImmutableDictionaryOf(params KeyValuePair[] items) where TKey : notnull => ImmutableDictionary.CreateRange(items); /// /// Create an immutable dictionary of the specified items. @@ -119,11 +94,7 @@ public static ImmutableDictionary ImmutableDictionaryOfThe underlying type of the immutable dictionary key. /// The underlying type of the immutable dictionary value. /// Returns an immutable dictionary populated with the specified items. - public static ImmutableDictionary ImmutableDictionaryOf( - params (TKey key, TValue value)[] items) where TKey : notnull - { - return ImmutableDictionary.CreateRange(items.Select(item => new KeyValuePair(item.key, item.value))); - } + public static ImmutableDictionary ImmutableDictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull => ImmutableDictionary.CreateRange(items.Select(item => new KeyValuePair(item.key, item.value))); /// /// Create a sorted dictionary of the specified items. @@ -132,11 +103,7 @@ public static ImmutableDictionary ImmutableDictionaryOfThe underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns a sorted dictionary populated with the specified items. - public static SortedDictionary SortedDictionaryOf( - params KeyValuePair[] items) where TKey : notnull - { - return new SortedDictionary(DictionaryOf(items)); - } + public static SortedDictionary SortedDictionaryOf(params KeyValuePair[] items) where TKey : notnull => new(DictionaryOf(items)); /// /// Create a sorted dictionary of the specified items. @@ -145,11 +112,7 @@ public static SortedDictionary SortedDictionaryOf( /// The underlying type of the sorted dictionary key. /// The underlying type of the sorted dictionary value. /// Returns a sorted dictionary populated with the specified items. - public static SortedDictionary SortedDictionaryOf( - params (TKey key, TValue value)[] items) where TKey : notnull - { - return new SortedDictionary(DictionaryOf(items)); - } + public static SortedDictionary SortedDictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull => new(DictionaryOf(items)); /// /// Create an immutable sorted dictionary of the specified items. @@ -158,11 +121,7 @@ public static SortedDictionary SortedDictionaryOf( /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an immutable sorted dictionary populated with the specified items. - public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( - params KeyValuePair[] items) where TKey : notnull - { - return ImmutableSortedDictionary.CreateRange(items); - } + public static ImmutableSortedDictionary ImmutableSortedDictionaryOf(params KeyValuePair[] items) where TKey : notnull => ImmutableSortedDictionary.CreateRange(items); /// /// Create an immutable sorted dictionary of the specified items. @@ -171,11 +130,7 @@ public static ImmutableSortedDictionary ImmutableSortedDictionaryO /// The underlying type of the immutable sorted dictionary key. /// The underlying type of the immutable sorted dictionary value. /// Returns an immutable sorted dictionary populated with the specified items. - public static ImmutableSortedDictionary ImmutableSortedDictionaryOf( - params (TKey key, TValue value)[] items) where TKey : notnull - { - return ImmutableSortedDictionary.CreateRange(items.Select(item => new KeyValuePair(item.key, item.value))); - } + public static ImmutableSortedDictionary ImmutableSortedDictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull => ImmutableSortedDictionary.CreateRange(items.Select(item => new KeyValuePair(item.key, item.value))); /// /// Creates a hash set of the specified items. @@ -183,10 +138,7 @@ public static ImmutableSortedDictionary ImmutableSortedDictionaryO /// The items which will populate the hash set. /// The underlying type of the hash set. /// Returns a hash set populated with the specified items. - public static HashSet HashSetOf(params T[] items) - { - return [..items]; - } + public static HashSet HashSetOf(params T[] items) => [..items]; /// /// Creates an immutable hash set of the specified items. @@ -194,10 +146,7 @@ public static HashSet HashSetOf(params T[] items) /// The items which will populate the immutable hash set. /// The underlying type of the immutable hash set. /// Returns an immutable hash set populated with the specified items. - public static ImmutableHashSet ImmutableHashSetOf(params T[] items) - { - return [..items]; - } + public static ImmutableHashSet ImmutableHashSetOf(params T[] items) => [..items]; /// /// Creates a sorted set of the specified items. @@ -205,10 +154,7 @@ public static ImmutableHashSet ImmutableHashSetOf(params T[] items) /// The items which will populate the sorted set. /// The underlying type of the sorted set. /// Returns a sorted set populated with the specified items. - public static SortedSet SortedSetOf(params T[] items) - { - return [..items]; - } + public static SortedSet SortedSetOf(params T[] items) => [..items]; /// /// Creates an immutable sorted set of the specified items. @@ -216,10 +162,7 @@ public static SortedSet SortedSetOf(params T[] items) /// The items which will populate the immutable sorted set. /// The underlying type of the immutable sorted set. /// Returns an immutable sorted set populated with the specified items. - public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) - { - return [..items]; - } + public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) => [..items]; /// /// Creates a stack of the specified items. @@ -227,10 +170,7 @@ public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) /// The items which will populate the stack. /// The underlying type of the stack. /// Returns a stack populated with the specified items. - public static Stack StackOf(params T[] items) - { - return new Stack(items); - } + public static Stack StackOf(params T[] items) => new(items); /// /// Creates an immutable stack of the specified items. @@ -238,10 +178,7 @@ public static Stack StackOf(params T[] items) /// The items which will populate the immutable stack. /// The underlying type of the immutable stack. /// Returns an immutable stack populated with the specified items. - public static ImmutableStack ImmutableStackOf(params T[] items) - { - return [..items]; - } + public static ImmutableStack ImmutableStackOf(params T[] items) => [..items]; /// /// Creates a queue of the specified items. @@ -249,10 +186,7 @@ public static ImmutableStack ImmutableStackOf(params T[] items) /// The items which will populate the queue. /// The underlying type of the queue. /// Returns a queue populated with the specified items. - public static Queue QueueOf(params T[] items) - { - return new Queue(items); - } + public static Queue QueueOf(params T[] items) => new(items); /// /// Creates an immutable queue of the specified items. @@ -260,8 +194,5 @@ public static Queue QueueOf(params T[] items) /// The items which will populate the immutable queue. /// The underlying type of the immutable queue. /// Returns an immutable queue populated with the specified items. - public static ImmutableQueue ImmutableQueueOf(params T[] items) - { - return [..items]; - } + public static ImmutableQueue ImmutableQueueOf(params T[] items) => [..items]; } diff --git a/OnixLabs.Core/Enumeration.Comparable.cs b/OnixLabs.Core/Enumeration.Comparable.cs index 03a988d..a850d61 100644 --- a/OnixLabs.Core/Enumeration.Comparable.cs +++ b/OnixLabs.Core/Enumeration.Comparable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,7 +16,7 @@ namespace OnixLabs.Core; -public abstract partial class Enumeration : IComparable, IComparable +public abstract partial class Enumeration { /// /// Compares the current instance with another object of the same type and returns an integer that indicates diff --git a/OnixLabs.Core/Enumeration.Equatable.cs b/OnixLabs.Core/Enumeration.Equatable.cs index 4efb291..90e3d49 100644 --- a/OnixLabs.Core/Enumeration.Equatable.cs +++ b/OnixLabs.Core/Enumeration.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,13 +16,13 @@ namespace OnixLabs.Core; -public abstract partial class Enumeration : IEquatable +public abstract partial class Enumeration { /// /// Indicates whether the current object is equal to another object of the same type. /// /// An object to compare with the current object. - /// Returns true if the current object is equal to the other parameter; otherwise, false. + /// Returns if the current object is equal to the other parameter; otherwise, . public bool Equals(T? other) { return ReferenceEquals(this, other) @@ -36,7 +36,7 @@ public bool Equals(T? other) /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public sealed override bool Equals(object? obj) { return Equals(obj as T); @@ -56,7 +56,7 @@ public sealed override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are equal; otherwise, false. + /// Returns if the instances are equal; otherwise, . public static bool operator ==(Enumeration left, Enumeration right) { return Equals(left, right); @@ -67,7 +67,7 @@ public sealed override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are not equal; otherwise, false. + /// Returns if the instances are not equal; otherwise, . public static bool operator !=(Enumeration left, Enumeration right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Enumeration.cs b/OnixLabs.Core/Enumeration.cs index aea73d2..6bd552f 100644 --- a/OnixLabs.Core/Enumeration.cs +++ b/OnixLabs.Core/Enumeration.cs @@ -1,24 +1,26 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; + namespace OnixLabs.Core; /// /// Represents the base class for implementing enumeration classes. /// /// The underlying enumeration type. -public abstract partial class Enumeration where T : Enumeration +public abstract partial class Enumeration : IEquatable, IComparable, IComparable where T : Enumeration { /// /// Initializes a new instance of the class. diff --git a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs index 9786d4c..6954ee2 100644 --- a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs +++ b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs @@ -34,7 +34,7 @@ public static class IEnumerableExtensions /// The selector function which will be used to select each property from each element. /// The underlying type of the . /// The underlying type of each selected element. - /// Returns true if all selected element properties are equal; otherwise false. + /// Returns if all selected element properties are equal; otherwise . public static bool AllEqualBy(this IEnumerable enumerable, Func selector) { ISet elements = enumerable.Select(selector).ToHashSet(); @@ -48,7 +48,7 @@ public static bool AllEqualBy(this IEnumerable enumerable, Func /// The selector function which will be used to select each property from each element. /// The underlying type of the . /// The underlying type of each selected element. - /// Returns true if any selected element properties are equal; otherwise false. + /// Returns if any selected element properties are equal; otherwise . public static bool AnyEqualBy(this IEnumerable enumerable, Func selector) { IList elements = enumerable.Select(selector).ToList(); @@ -97,7 +97,7 @@ public static int GetContentHashCode(this IEnumerable enumerable) /// /// The on which to perform the operation. /// he underlying type of the . - /// Returns true if the is empty; otherwise, false. + /// Returns if the is empty; otherwise, . public static bool IsEmpty(this IEnumerable enumerable) { return !enumerable.Any(); @@ -108,7 +108,7 @@ public static bool IsEmpty(this IEnumerable enumerable) /// /// The on which to perform the operation. /// The underlying type of the . - /// Returns true if the is not empty; otherwise, false. + /// Returns if the is not empty; otherwise, . public static bool IsNotEmpty(this IEnumerable enumerable) { return !enumerable.IsEmpty(); @@ -119,7 +119,7 @@ public static bool IsNotEmpty(this IEnumerable enumerable) /// /// The on which to perform the operation. /// The underlying type of the . - /// Returns true if the contains a single element; otherwise, false. + /// Returns if the contains a single element; otherwise, . public static bool IsSingle(this IEnumerable enumerable) { return enumerable.LongCount() == 1; @@ -130,7 +130,7 @@ public static bool IsSingle(this IEnumerable enumerable) /// /// The on which to perform the operation. /// The underlying type of the . - /// Returns true if the contains an even number of elements; otherwise, false. + /// Returns if the contains an even number of elements; otherwise, . public static bool IsCountEven(this IEnumerable enumerable) { return enumerable.LongCount() % 2 == 0; @@ -141,7 +141,7 @@ public static bool IsCountEven(this IEnumerable enumerable) /// /// The on which to perform the operation. /// The underlying type of the . - /// Returns true if the contains an odd number of elements; otherwise, false. + /// Returns if the contains an odd number of elements; otherwise, . public static bool IsCountOdd(this IEnumerable enumerable) { return !enumerable.IsCountEven(); @@ -176,7 +176,7 @@ public static string JoinToString(this IEnumerable enumerable, string sepa /// The on which to perform the operation. /// The function to test each element for a condition. /// The underlying type of the . - /// Returns true if none of the elements of the current satisfy the specified predicate condition; otherwise, false. + /// Returns if none of the elements of the current satisfy the specified predicate condition; otherwise, . public static bool None(this IEnumerable enumerable, Func predicate) { return !enumerable.Any(predicate); diff --git a/OnixLabs.Core/Preconditions.cs b/OnixLabs.Core/Preconditions.cs index 4811d45..313c6a3 100644 --- a/OnixLabs.Core/Preconditions.cs +++ b/OnixLabs.Core/Preconditions.cs @@ -13,7 +13,6 @@ // limitations under the License. using System; -using System.Runtime.CompilerServices; using OnixLabs.Core.Linq; namespace OnixLabs.Core; @@ -24,7 +23,7 @@ namespace OnixLabs.Core; public static class Preconditions { /// - /// Performs a general pre-condition check, which fails if the condition returns false. + /// Performs a general pre-condition check, which fails if the condition returns . /// /// The condition to check. /// The exception message to throw in the event that the condition fails. @@ -48,7 +47,7 @@ public static T CheckNotNull(T? value, string message = "Argument must not be } /// - /// Performs a general pre-condition requirement, which fails if the condition returns false. + /// Performs a general pre-condition requirement, which fails if the condition returns . /// /// The condition of the requirement. /// The exception message to throw in the event that the condition fails. diff --git a/OnixLabs.Core/Text/Base16.Equatable.cs b/OnixLabs.Core/Text/Base16.Equatable.cs index 22150bf..7455877 100644 --- a/OnixLabs.Core/Text/Base16.Equatable.cs +++ b/OnixLabs.Core/Text/Base16.Equatable.cs @@ -24,7 +24,7 @@ public readonly partial struct Base16 /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public bool Equals(Base16 other) { return value.SequenceEqual(other.value); @@ -34,7 +34,7 @@ public bool Equals(Base16 other) /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return obj is Base16 other && Equals(other); @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are equal; otherwise, false. + /// Returns if the instances are equal; otherwise, . public static bool operator ==(Base16 left, Base16 right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are not equal; otherwise, false. + /// Returns if the instances are not equal; otherwise, . public static bool operator !=(Base16 left, Base16 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base16.Parse.cs b/OnixLabs.Core/Text/Base16.Parse.cs index fc850d3..0e47928 100644 --- a/OnixLabs.Core/Text/Base16.Parse.cs +++ b/OnixLabs.Core/Text/Base16.Parse.cs @@ -59,7 +59,7 @@ public static Base16 Parse(ReadOnlySpan value, IFormatProvider? provider = /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out Base16 result) { return TryParse(value.AsSpan(), provider, out result); @@ -77,7 +77,7 @@ public static bool TryParse(string? value, IFormatProvider? provider, out Base16 /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base16 result) { try diff --git a/OnixLabs.Core/Text/Base32.Equatable.cs b/OnixLabs.Core/Text/Base32.Equatable.cs index 086d9d7..56c1294 100644 --- a/OnixLabs.Core/Text/Base32.Equatable.cs +++ b/OnixLabs.Core/Text/Base32.Equatable.cs @@ -24,7 +24,7 @@ public readonly partial struct Base32 /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public bool Equals(Base32 other) { return value.SequenceEqual(other.value); @@ -34,7 +34,7 @@ public bool Equals(Base32 other) /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return obj is Base32 other && Equals(other); @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are equal; otherwise, false. + /// Returns if the instances are equal; otherwise, . public static bool operator ==(Base32 left, Base32 right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are not equal; otherwise, false. + /// Returns if the instances are not equal; otherwise, . public static bool operator !=(Base32 left, Base32 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base32.Parse.cs b/OnixLabs.Core/Text/Base32.Parse.cs index cee39fd..9de5c71 100644 --- a/OnixLabs.Core/Text/Base32.Parse.cs +++ b/OnixLabs.Core/Text/Base32.Parse.cs @@ -50,7 +50,7 @@ public static Base32 Parse(ReadOnlySpan value, IFormatProvider? provider = /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out Base32 result) { return TryParse(value.AsSpan(), provider, out result); @@ -65,7 +65,7 @@ public static bool TryParse(string? value, IFormatProvider? provider, out Base32 /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base32 result) { try diff --git a/OnixLabs.Core/Text/Base58.Equatable.cs b/OnixLabs.Core/Text/Base58.Equatable.cs index 24cd0b4..e75e43a 100644 --- a/OnixLabs.Core/Text/Base58.Equatable.cs +++ b/OnixLabs.Core/Text/Base58.Equatable.cs @@ -25,7 +25,7 @@ public readonly partial struct Base58 /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public bool Equals(Base58 other) { return value.SequenceEqual(other.value); @@ -35,7 +35,7 @@ public bool Equals(Base58 other) /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return obj is Base58 other && Equals(other); @@ -55,7 +55,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are equal; otherwise, false. + /// Returns if the instances are equal; otherwise, . public static bool operator ==(Base58 left, Base58 right) { return Equals(left, right); @@ -66,7 +66,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are not equal; otherwise, false. + /// Returns if the instances are not equal; otherwise, . public static bool operator !=(Base58 left, Base58 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base58.Parse.cs b/OnixLabs.Core/Text/Base58.Parse.cs index 08f45c4..978f083 100644 --- a/OnixLabs.Core/Text/Base58.Parse.cs +++ b/OnixLabs.Core/Text/Base58.Parse.cs @@ -73,7 +73,7 @@ public static Base58 ParseWithChecksum(ReadOnlySpan value, IFormatProvider /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out Base58 result) { return TryParse(value.AsSpan(), provider, out result); @@ -88,7 +88,7 @@ public static bool TryParse(string? value, IFormatProvider? provider, out Base58 /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base58 result) { try @@ -114,7 +114,7 @@ public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParseWithChecksum(string? value, IFormatProvider? provider, out Base58 result) { return TryParseWithChecksum(value.AsSpan(), provider, out result); @@ -129,7 +129,7 @@ public static bool TryParseWithChecksum(string? value, IFormatProvider? provider /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParseWithChecksum(ReadOnlySpan value, IFormatProvider? provider, out Base58 result) { try diff --git a/OnixLabs.Core/Text/Base64.Equatable.cs b/OnixLabs.Core/Text/Base64.Equatable.cs index 1edf6c3..1818dbe 100644 --- a/OnixLabs.Core/Text/Base64.Equatable.cs +++ b/OnixLabs.Core/Text/Base64.Equatable.cs @@ -24,7 +24,7 @@ public readonly partial struct Base64 /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public bool Equals(Base64 other) { return value.SequenceEqual(other.value); @@ -34,7 +34,7 @@ public bool Equals(Base64 other) /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// Returns true if the object is equal to the current instance; otherwise, false. + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return obj is Base64 other && Equals(other); @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are equal; otherwise, false. + /// Returns if the instances are equal; otherwise, . public static bool operator ==(Base64 left, Base64 right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns true if the instances are not equal; otherwise, false. + /// Returns if the instances are not equal; otherwise, . public static bool operator !=(Base64 left, Base64 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base64.Parse.cs b/OnixLabs.Core/Text/Base64.Parse.cs index 7225916..9d87d12 100644 --- a/OnixLabs.Core/Text/Base64.Parse.cs +++ b/OnixLabs.Core/Text/Base64.Parse.cs @@ -59,7 +59,7 @@ public static Base64 Parse(ReadOnlySpan value, IFormatProvider? provider = /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out Base64 result) { return TryParse(value.AsSpan(), provider, out result); @@ -77,7 +77,7 @@ public static bool TryParse(string? value, IFormatProvider? provider, out Base64 /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base64 result) { try diff --git a/OnixLabs.Numerics/BigDecimal.Comparable.cs b/OnixLabs.Numerics/BigDecimal.Comparable.cs index 18f9349..c566ca8 100644 --- a/OnixLabs.Numerics/BigDecimal.Comparable.cs +++ b/OnixLabs.Numerics/BigDecimal.Comparable.cs @@ -57,7 +57,7 @@ public int CompareTo(BigDecimal other) /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns True if the left-hand operand is greater than right-hand operand; otherwise, false. + /// Returns if the left-hand operand is greater than right-hand operand; otherwise, . public static bool operator >(BigDecimal left, BigDecimal right) { return BigDecimalOrdinalityComparer.Default.IsGreaterThan(left, right); @@ -68,7 +68,7 @@ public int CompareTo(BigDecimal other) /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is greater than or equal to the right-hand operand; otherwise, false. + /// Returns if the left-hand operand is greater than or equal to the right-hand operand; otherwise, . public static bool operator >=(BigDecimal left, BigDecimal right) { return BigDecimalOrdinalityComparer.Default.IsGreaterThanOrEqual(left, right); @@ -79,7 +79,7 @@ public int CompareTo(BigDecimal other) /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is less than the right-hand operand; otherwise, false. + /// Returns if the left-hand operand is less than the right-hand operand; otherwise, . public static bool operator <(BigDecimal left, BigDecimal right) { return BigDecimalOrdinalityComparer.Default.IsLessThan(left, right); @@ -90,7 +90,7 @@ public int CompareTo(BigDecimal other) /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is less than or equal to the right-hand operand; otherwise, false. + /// Returns if the left-hand operand is less than or equal to the right-hand operand; otherwise, . public static bool operator <=(BigDecimal left, BigDecimal right) { return BigDecimalOrdinalityComparer.Default.IsLessThanOrEqual(left, right); diff --git a/OnixLabs.Numerics/BigDecimal.Convertible.cs b/OnixLabs.Numerics/BigDecimal.Convertible.cs index 6bd8a52..1e6408c 100644 --- a/OnixLabs.Numerics/BigDecimal.Convertible.cs +++ b/OnixLabs.Numerics/BigDecimal.Convertible.cs @@ -16,7 +16,7 @@ namespace OnixLabs.Numerics; -public readonly partial struct BigDecimal : IConvertible +public readonly partial struct BigDecimal { /// /// Gets the for the current instance. diff --git a/OnixLabs.Numerics/BigDecimal.Equatable.cs b/OnixLabs.Numerics/BigDecimal.Equatable.cs index 9ab9859..094196c 100644 --- a/OnixLabs.Numerics/BigDecimal.Equatable.cs +++ b/OnixLabs.Numerics/BigDecimal.Equatable.cs @@ -24,7 +24,7 @@ public readonly partial struct BigDecimal /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the two specified instances are equal; otherwise, false. + /// Returns if the two specified instances are equal; otherwise, . public static bool Equals(BigDecimal left, BigDecimal right) { return Equals(left, right, BigDecimalEqualityComparer.Strict); @@ -36,7 +36,7 @@ public static bool Equals(BigDecimal left, BigDecimal right) /// The left-hand value to compare. /// The right-hand value to compare. /// The equality comparer to use to determine equality. - /// Returns true if the two specified instances are equal; otherwise, false. + /// Returns if the two specified instances are equal; otherwise, . public static bool Equals(BigDecimal left, BigDecimal right, BigDecimalEqualityComparer comparer) { return comparer.Equals(left, right); @@ -47,7 +47,7 @@ public static bool Equals(BigDecimal left, BigDecimal right, BigDecimalEqualityC /// This method implements the comparer. /// /// The other instance of to compare with the current instance. - /// Returns true if the current instance is equal to the specified other instance; otherwise, false. + /// Returns if the current instance is equal to the specified other instance; otherwise, . public bool Equals(BigDecimal other) { return Equals(this, other); @@ -58,7 +58,7 @@ public bool Equals(BigDecimal other) /// /// The other instance of to compare with the current instance. /// The equality comparer to use to determine equality. - /// Returns true if the current instance is equal to the specified other instance; otherwise, false. + /// Returns if the current instance is equal to the specified other instance; otherwise, . public bool Equals(BigDecimal other, BigDecimalEqualityComparer comparer) { return Equals(this, other, comparer); @@ -69,7 +69,7 @@ public bool Equals(BigDecimal other, BigDecimalEqualityComparer comparer) /// This method implements the comparer. /// /// The object to check for equality. - /// Returns true if the object is equal to this instance; otherwise, false. + /// Returns if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return obj is BigDecimal other && Equals(other); @@ -80,7 +80,7 @@ public override bool Equals(object? obj) /// /// The object to check for equality. /// The equality comparer to use to determine equality. - /// Returns true if the object is equal to this instance; otherwise, false. + /// Returns if the object is equal to this instance; otherwise, . public bool Equals(object? obj, BigDecimalEqualityComparer comparer) { return obj is BigDecimal other && Equals(other, comparer); @@ -102,7 +102,7 @@ public override int GetHashCode() /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the two specified instances are equal; otherwise, false. + /// Returns if the two specified instances are equal; otherwise, . public static bool operator ==(BigDecimal left, BigDecimal right) { return Equals(left, right, BigDecimalEqualityComparer.Semantic); @@ -114,7 +114,7 @@ public override int GetHashCode() /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the two specified instances are not equal; otherwise, false. + /// Returns if the two specified instances are not equal; otherwise, . public static bool operator !=(BigDecimal left, BigDecimal right) { return Equals(left, right, BigDecimalEqualityComparer.Semantic); diff --git a/OnixLabs.Numerics/BigDecimal.Is.cs b/OnixLabs.Numerics/BigDecimal.Is.cs index aee2f78..4a4631a 100644 --- a/OnixLabs.Numerics/BigDecimal.Is.cs +++ b/OnixLabs.Numerics/BigDecimal.Is.cs @@ -22,7 +22,7 @@ public readonly partial struct BigDecimal /// Determines if a value represents an integral number. /// /// The value to be checked. - /// Returns true if the value is an integer; otherwise, false. + /// Returns if the value is an integer; otherwise, . public static bool IsInteger(BigDecimal value) { return value.number.Fraction == BigInteger.Zero; @@ -32,7 +32,7 @@ public static bool IsInteger(BigDecimal value) /// Determines if a value represents an even integral number. /// /// The value to be checked. - /// Returns true if the value is an even integer; otherwise, false. + /// Returns if the value is an even integer; otherwise, . public static bool IsEvenInteger(BigDecimal value) { return IsInteger(value) && BigInteger.IsEvenInteger(value.number.Integer); @@ -42,7 +42,7 @@ public static bool IsEvenInteger(BigDecimal value) /// Determines if a value represents an odd integral number. /// /// The value to be checked. - /// Returns true if the value is an odd integer; otherwise, false. + /// Returns if the value is an odd integer; otherwise, . public static bool IsOddInteger(BigDecimal value) { return IsInteger(value) && BigInteger.IsOddInteger(value.number.Integer); @@ -52,7 +52,7 @@ public static bool IsOddInteger(BigDecimal value) /// Determines if a value is negative. /// /// The value to be checked. - /// Returns true if the value is negative; otherwise, false. + /// Returns if the value is negative; otherwise, . public static bool IsNegative(BigDecimal value) { return BigInteger.IsNegative(value.UnscaledValue); @@ -62,7 +62,7 @@ public static bool IsNegative(BigDecimal value) /// Determines if a value is positive. /// /// The value to be checked. - /// Returns true if the value is positive; otherwise, false. + /// Returns if the value is positive; otherwise, . public static bool IsPositive(BigDecimal value) { return BigInteger.IsPositive(value.UnscaledValue); @@ -72,7 +72,7 @@ public static bool IsPositive(BigDecimal value) /// Determines if a value is zero. /// /// The value to be checked. - /// Returns true if the value is zero; otherwise, false. + /// Returns if the value is zero; otherwise, . public static bool IsZero(BigDecimal value) { return value.UnscaledValue == BigInteger.Zero; @@ -82,7 +82,7 @@ public static bool IsZero(BigDecimal value) /// Determines if a value is in its canonical representation. /// /// The value to be checked. - /// Returns true if value is in its canonical representation; otherwise, false. + /// Returns if value is in its canonical representation; otherwise, . static bool INumberBase.IsCanonical(BigDecimal value) { return true; @@ -92,7 +92,7 @@ static bool INumberBase.IsCanonical(BigDecimal value) /// Determines if a value represents a complex number. /// /// The value to be checked. - /// Returns true if value is a complex number; otherwise, false. + /// Returns if value is a complex number; otherwise, . static bool INumberBase.IsComplexNumber(BigDecimal value) { return false; @@ -102,7 +102,7 @@ static bool INumberBase.IsComplexNumber(BigDecimal value) /// Determines if a value is finite. /// /// The value to be checked. - /// Returns true if value is finite; otherwise, false. + /// Returns if value is finite; otherwise, . static bool INumberBase.IsFinite(BigDecimal value) { return true; @@ -112,7 +112,7 @@ static bool INumberBase.IsFinite(BigDecimal value) /// Determines if a value represents a pure imaginary number. /// /// The value to be checked. - /// Returns true if value is a pure imaginary number; otherwise, false. + /// Returns if value is a pure imaginary number; otherwise, . static bool INumberBase.IsImaginaryNumber(BigDecimal value) { return false; @@ -122,7 +122,7 @@ static bool INumberBase.IsImaginaryNumber(BigDecimal value) /// Determines if a value is infinite. /// /// The value to be checked. - /// Returns true if value is infinite; otherwise, false. + /// Returns if value is infinite; otherwise, . static bool INumberBase.IsInfinity(BigDecimal value) { return false; @@ -132,7 +132,7 @@ static bool INumberBase.IsInfinity(BigDecimal value) /// Determines if a value is NaN. /// /// The value to be checked. - /// Returns true if value is NaN; otherwise, false. + /// Returns if value is NaN; otherwise, . static bool INumberBase.IsNaN(BigDecimal value) { return false; @@ -142,7 +142,7 @@ static bool INumberBase.IsNaN(BigDecimal value) /// Determines if a value is negative infinity. /// /// The value to be checked. - /// Returns true if value is negative infinity; otherwise, false. + /// Returns if value is negative infinity; otherwise, . static bool INumberBase.IsNegativeInfinity(BigDecimal value) { return false; @@ -152,7 +152,7 @@ static bool INumberBase.IsNegativeInfinity(BigDecimal value) /// Determines if a value is normal. /// /// The value to be checked. - /// Returns true if value is normal; otherwise, false. + /// Returns if value is normal; otherwise, . static bool INumberBase.IsNormal(BigDecimal value) { return true; @@ -162,7 +162,7 @@ static bool INumberBase.IsNormal(BigDecimal value) /// Determines if a value is positive infinity. /// /// The value to be checked. - /// Returns true if value is positive infinity; otherwise, false. + /// Returns if value is positive infinity; otherwise, . static bool INumberBase.IsPositiveInfinity(BigDecimal value) { return false; @@ -172,7 +172,7 @@ static bool INumberBase.IsPositiveInfinity(BigDecimal value) /// Determines if a value represents a real number. /// /// The value to be checked. - /// Returns true if value is a real number; otherwise, false + /// Returns if value is a real number; otherwise, static bool INumberBase.IsRealNumber(BigDecimal value) { return true; @@ -182,7 +182,7 @@ static bool INumberBase.IsRealNumber(BigDecimal value) /// Determines if a value is subnormal. /// /// The value to be checked. - /// Returns true if value is subnormal; otherwise, false. + /// Returns if value is subnormal; otherwise, . static bool INumberBase.IsSubnormal(BigDecimal value) { return false; diff --git a/OnixLabs.Numerics/BigDecimal.Parse.cs b/OnixLabs.Numerics/BigDecimal.Parse.cs index 7f30ada..5219347 100644 --- a/OnixLabs.Numerics/BigDecimal.Parse.cs +++ b/OnixLabs.Numerics/BigDecimal.Parse.cs @@ -75,7 +75,7 @@ public static BigDecimal Parse(ReadOnlySpan value, NumberStyles style, IFo /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, out BigDecimal result) { return TryParse(value.AsSpan(), out result); @@ -90,7 +90,7 @@ public static bool TryParse(string? value, out BigDecimal result) /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out BigDecimal result) { return TryParse(value.AsSpan(), provider, out result); @@ -106,7 +106,7 @@ public static bool TryParse(string? value, IFormatProvider? provider, out BigDec /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, NumberStyles style, IFormatProvider? provider, out BigDecimal result) { return TryParse(value.AsSpan(), style, provider, out result); @@ -120,7 +120,7 @@ public static bool TryParse(string? value, NumberStyles style, IFormatProvider? /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, out BigDecimal result) { return TryParse(value, DefaultCulture, out result); @@ -135,7 +135,7 @@ public static bool TryParse(ReadOnlySpan value, out BigDecimal result) /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out BigDecimal result) { return TryParse(value, DefaultNumberStyles, provider, out result); @@ -151,7 +151,7 @@ public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, NumberStyles style, IFormatProvider? provider, out BigDecimal result) { CultureInfo info = provider as CultureInfo ?? DefaultCulture; diff --git a/OnixLabs.Numerics/BigDecimal.To.cs b/OnixLabs.Numerics/BigDecimal.To.cs index f453a5b..a8a4aab 100644 --- a/OnixLabs.Numerics/BigDecimal.To.cs +++ b/OnixLabs.Numerics/BigDecimal.To.cs @@ -71,7 +71,7 @@ public string ToString(ReadOnlySpan format, IFormatProvider? formatProvide /// The format specifier from which to obtain the desired scale. /// The number format of the target culture that determines default scales for specific formats. /// The value with a correctly applied scale. - /// Returns if the scale is applied correctly; otherwise, false. + /// Returns if the scale is applied correctly; otherwise, . private bool TryGetScaledNumberInfo(ReadOnlySpan format, NumberFormatInfo numberFormat, out NumberInfo result) { const MidpointRounding mode = MidpointRounding.AwayFromZero; diff --git a/OnixLabs.Numerics/BigDecimal.cs b/OnixLabs.Numerics/BigDecimal.cs index 629e230..f6b697e 100644 --- a/OnixLabs.Numerics/BigDecimal.cs +++ b/OnixLabs.Numerics/BigDecimal.cs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Numerics; namespace OnixLabs.Numerics; @@ -19,7 +20,7 @@ namespace OnixLabs.Numerics; /// /// Represents an arbitrarily large signed decimal. /// -public readonly partial struct BigDecimal : IFloatingPoint +public readonly partial struct BigDecimal : IFloatingPoint, IConvertible { /// /// The underlying that represents the current value. diff --git a/OnixLabs.Numerics/Ieee754Converter.cs b/OnixLabs.Numerics/Ieee754Converter.cs index 3df5c91..2a4a7fd 100644 --- a/OnixLabs.Numerics/Ieee754Converter.cs +++ b/OnixLabs.Numerics/Ieee754Converter.cs @@ -190,7 +190,7 @@ private static NumberInfo ConvertFromDecimal(T value) where T : IBinaryFloati /// The value to check. /// The result if the number is zero or one. /// The underlying type of the value. - /// Returns true if the specified IEEE 754 binary floating-point number is zero or one; otherwise, false. + /// Returns if the specified IEEE 754 binary floating-point number is zero or one; otherwise, . private static bool IsZeroOrOne(T value, out NumberInfo result) where T : IBinaryFloatingPointIeee754 { if (value == T.Zero || value == T.NegativeZero) diff --git a/OnixLabs.Numerics/NumberInfo.Comparable.cs b/OnixLabs.Numerics/NumberInfo.Comparable.cs index 6a427da..8c71bd4 100644 --- a/OnixLabs.Numerics/NumberInfo.Comparable.cs +++ b/OnixLabs.Numerics/NumberInfo.Comparable.cs @@ -12,12 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using System.Numerics; - namespace OnixLabs.Numerics; -public readonly partial struct NumberInfo : IComparable, IComparable, IComparisonOperators +public readonly partial struct NumberInfo { /// /// Compares two values and returns an integer that indicates @@ -60,7 +57,7 @@ public int CompareTo(object? obj) /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns True if the left-hand operand is greater than right-hand operand; otherwise, false. + /// Returns if the left-hand operand is greater than right-hand operand; otherwise, . public static bool operator >(NumberInfo left, NumberInfo right) { return NumberInfoOrdinalityComparer.Default.IsGreaterThan(left, right); @@ -71,7 +68,7 @@ public int CompareTo(object? obj) /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is greater than or equal to the right-hand operand; otherwise, false. + /// Returns if the left-hand operand is greater than or equal to the right-hand operand; otherwise, . public static bool operator >=(NumberInfo left, NumberInfo right) { return NumberInfoOrdinalityComparer.Default.IsGreaterThanOrEqual(left, right); @@ -82,7 +79,7 @@ public int CompareTo(object? obj) /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is less than the right-hand operand; otherwise, false. + /// Returns if the left-hand operand is less than the right-hand operand; otherwise, . public static bool operator <(NumberInfo left, NumberInfo right) { return NumberInfoOrdinalityComparer.Default.IsLessThan(left, right); @@ -93,7 +90,7 @@ public int CompareTo(object? obj) /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the left-hand operand is less than or equal to the right-hand operand; otherwise, false. + /// Returns if the left-hand operand is less than or equal to the right-hand operand; otherwise, . public static bool operator <=(NumberInfo left, NumberInfo right) { return NumberInfoOrdinalityComparer.Default.IsLessThanOrEqual(left, right); diff --git a/OnixLabs.Numerics/NumberInfo.Equatable.cs b/OnixLabs.Numerics/NumberInfo.Equatable.cs index 08f28ae..fba2bad 100644 --- a/OnixLabs.Numerics/NumberInfo.Equatable.cs +++ b/OnixLabs.Numerics/NumberInfo.Equatable.cs @@ -16,7 +16,7 @@ namespace OnixLabs.Numerics; -public readonly partial struct NumberInfo : IEquatable +public readonly partial struct NumberInfo { /// /// Compares two instances of to determine whether their values are equal. @@ -24,7 +24,7 @@ namespace OnixLabs.Numerics; /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the two specified instances are equal; otherwise, false. + /// Returns if the two specified instances are equal; otherwise, . public static bool Equals(NumberInfo left, NumberInfo right) { return Equals(left, right, NumberInfoEqualityComparer.Strict); @@ -36,7 +36,7 @@ public static bool Equals(NumberInfo left, NumberInfo right) /// The left-hand value to compare. /// The right-hand value to compare. /// The equality comparer to use to determine equality. - /// Returns true if the two specified instances are equal; otherwise, false. + /// Returns if the two specified instances are equal; otherwise, . public static bool Equals(NumberInfo left, NumberInfo right, NumberInfoEqualityComparer comparer) { return comparer.Equals(left, right); @@ -47,7 +47,7 @@ public static bool Equals(NumberInfo left, NumberInfo right, NumberInfoEqualityC /// This method implements the comparer. /// /// The other instance of to compare with the current instance. - /// Returns true if the current instance is equal to the specified other instance; otherwise, false. + /// Returns if the current instance is equal to the specified other instance; otherwise, . public bool Equals(NumberInfo other) { return Equals(this, other); @@ -58,7 +58,7 @@ public bool Equals(NumberInfo other) /// /// The other instance of to compare with the current instance. /// The equality comparer to use to determine equality. - /// Returns true if the current instance is equal to the specified other instance; otherwise, false. + /// Returns if the current instance is equal to the specified other instance; otherwise, . public bool Equals(NumberInfo other, NumberInfoEqualityComparer comparer) { return Equals(this, other, comparer); @@ -69,7 +69,7 @@ public bool Equals(NumberInfo other, NumberInfoEqualityComparer comparer) /// This method implements the comparer. /// /// The object to check for equality. - /// Returns true if the object is equal to this instance; otherwise, false. + /// Returns if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return obj is NumberInfo other && Equals(other); @@ -80,7 +80,7 @@ public override bool Equals(object? obj) /// /// The object to check for equality. /// The equality comparer to use to determine equality. - /// Returns true if the object is equal to this instance; otherwise, false. + /// Returns if the object is equal to this instance; otherwise, . public bool Equals(object? obj, NumberInfoEqualityComparer comparer) { return obj is NumberInfo other && Equals(other, comparer); @@ -102,7 +102,7 @@ public override int GetHashCode() /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the two specified instances are equal; otherwise, false. + /// Returns if the two specified instances are equal; otherwise, . public static bool operator ==(NumberInfo left, NumberInfo right) { return Equals(left, right, NumberInfoEqualityComparer.Semantic); @@ -114,7 +114,7 @@ public override int GetHashCode() /// /// The left-hand value to compare. /// The right-hand value to compare. - /// Returns true if the two specified instances are not equal; otherwise, false. + /// Returns if the two specified instances are not equal; otherwise, . public static bool operator !=(NumberInfo left, NumberInfo right) { return Equals(left, right, NumberInfoEqualityComparer.Semantic); diff --git a/OnixLabs.Numerics/NumberInfo.Parse.cs b/OnixLabs.Numerics/NumberInfo.Parse.cs index 6827a73..51c760d 100644 --- a/OnixLabs.Numerics/NumberInfo.Parse.cs +++ b/OnixLabs.Numerics/NumberInfo.Parse.cs @@ -17,7 +17,7 @@ namespace OnixLabs.Numerics; -public readonly partial struct NumberInfo : ISpanParsable +public readonly partial struct NumberInfo { /// /// Parses the specified value into a value. @@ -75,7 +75,7 @@ public static NumberInfo Parse(ReadOnlySpan value, NumberStyles style, IFo /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, out NumberInfo result) { return TryParse(value.AsSpan(), out result); @@ -90,7 +90,7 @@ public static bool TryParse(string? value, out NumberInfo result) /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out NumberInfo result) { return TryParse(value.AsSpan(), provider, out result); @@ -106,7 +106,7 @@ public static bool TryParse(string? value, IFormatProvider? provider, out Number /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(string? value, NumberStyles style, IFormatProvider? provider, out NumberInfo result) { return TryParse(value.AsSpan(), style, provider, out result); @@ -120,7 +120,7 @@ public static bool TryParse(string? value, NumberStyles style, IFormatProvider? /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, out NumberInfo result) { return TryParse(value, DefaultCulture, out result); @@ -135,7 +135,7 @@ public static bool TryParse(ReadOnlySpan value, out NumberInfo result) /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out NumberInfo result) { return TryParse(value, DefaultNumberStyles, provider, out result); @@ -151,7 +151,7 @@ public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, /// On return, contains the result of parsing the specified value, /// or the default value in the event that the specified value could not be parsed. /// - /// Returns true if the specified value was parsed successfully; otherwise, false. + /// Returns if the specified value was parsed successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, NumberStyles style, IFormatProvider? provider, out NumberInfo result) { CultureInfo info = provider as CultureInfo ?? DefaultCulture; diff --git a/OnixLabs.Numerics/NumberInfo.To.cs b/OnixLabs.Numerics/NumberInfo.To.cs index 43ff78d..ddf9be3 100644 --- a/OnixLabs.Numerics/NumberInfo.To.cs +++ b/OnixLabs.Numerics/NumberInfo.To.cs @@ -17,7 +17,7 @@ namespace OnixLabs.Numerics; -public readonly partial struct NumberInfo : IFormattable +public readonly partial struct NumberInfo { /// /// Formats the value of the current instance using the default format. diff --git a/OnixLabs.Numerics/NumberInfo.cs b/OnixLabs.Numerics/NumberInfo.cs index 864174e..2002e39 100644 --- a/OnixLabs.Numerics/NumberInfo.cs +++ b/OnixLabs.Numerics/NumberInfo.cs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Numerics; namespace OnixLabs.Numerics; @@ -19,7 +20,13 @@ namespace OnixLabs.Numerics; /// /// Represents component information about rational numbers. /// -public readonly partial struct NumberInfo +public readonly partial struct NumberInfo : + IEquatable, + IComparable, + IComparable, + IComparisonOperators, + ISpanParsable, + IFormattable { /// /// Prevents a default instance of the struct from being created. diff --git a/OnixLabs.Numerics/NumericsExtensions.cs b/OnixLabs.Numerics/NumericsExtensions.cs index 217620b..185ba6e 100644 --- a/OnixLabs.Numerics/NumericsExtensions.cs +++ b/OnixLabs.Numerics/NumericsExtensions.cs @@ -74,7 +74,7 @@ private static BigInteger GetUnscaledInteger(this T value, int scale, ScaleMo /// The inclusive minimum value. /// The inclusive maximum value. /// The underlying type. - /// Returns true if the current value is inclusively between the specified minimum and maximum values; otherwise false. + /// Returns if the current value is inclusively between the specified minimum and maximum values; otherwise, . public static bool IsBetween(this T value, T minimum, T maximum) where T : INumber { return value >= minimum && value <= maximum; diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs index b3bb450..63e5058 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,7 +24,7 @@ namespace OnixLabs.Security.Cryptography; /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public bool Equals(DigitalSignature other) { return other.Value.SequenceEqual(Value); @@ -34,7 +34,7 @@ public bool Equals(DigitalSignature other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return obj is DigitalSignature other && Equals(other); @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(DigitalSignature left, DigitalSignature right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(DigitalSignature left, DigitalSignature right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs index d743eff..11aff44 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,7 +23,7 @@ public readonly partial struct DigitalSignature /// /// The unsigned data to validate. /// The public key to validate. - /// Returns true if this is valid; otherwise, false. + /// Returns if this is valid; otherwise, . public bool IsDataValid(byte[] unsignedData, PublicKey key) { return key.IsDataValid(this, unsignedData); @@ -34,7 +34,7 @@ public bool IsDataValid(byte[] unsignedData, PublicKey key) /// /// The unsigned data to validate. /// The public key to validate. - /// Returns true if this is valid; otherwise, false. + /// Returns if this is valid; otherwise, . public bool IsHashValid(byte[] unsignedHash, PublicKey key) { return key.IsHashValid(this, unsignedHash); @@ -45,7 +45,7 @@ public bool IsHashValid(byte[] unsignedHash, PublicKey key) /// /// The unsigned data to validate. /// The public key to validate. - /// Returns true if this is valid; otherwise, false. + /// Returns if this is valid; otherwise, . public bool IsHashValid(Hash unsignedHash, PublicKey key) { byte[] unsignedHashBytes = unsignedHash.ToByteArray(); diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs index 51b7527..ac2b6ff 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,7 +23,7 @@ public sealed partial class EcdsaPublicKey /// /// The to validate. /// The unsigned data to validate. - /// Returns true if the specified was signed by the private component of this public key; otherwise, false. + /// Returns if the specified was signed by the private component of this public key; otherwise, . public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData) { using ECDsa publicKey = ECDsa.Create(); @@ -38,7 +38,7 @@ public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData /// /// The to validate. /// The unsigned hash to validate. - /// Returns true if the specified was signed by the private component of this public key; otherwise, false. + /// Returns if the specified was signed by the private component of this public key; otherwise, . public override bool IsHashValid(DigitalSignature signature, byte[] unsignedHash) { using ECDsa publicKey = ECDsa.Create(); diff --git a/OnixLabs.Security.Cryptography/Hash.Equatable.cs b/OnixLabs.Security.Cryptography/Hash.Equatable.cs index 8a610a7..a776a17 100644 --- a/OnixLabs.Security.Cryptography/Hash.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Hash.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,7 +24,7 @@ namespace OnixLabs.Security.Cryptography; /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public bool Equals(Hash other) { return other.AlgorithmType == AlgorithmType && other.Value.SequenceEqual(Value); @@ -34,7 +34,7 @@ public bool Equals(Hash other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return obj is Hash other && Equals(other); @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(Hash left, Hash right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(Hash left, Hash right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/Hash.Parse.cs b/OnixLabs.Security.Cryptography/Hash.Parse.cs index 742f87c..6b8abf2 100644 --- a/OnixLabs.Security.Cryptography/Hash.Parse.cs +++ b/OnixLabs.Security.Cryptography/Hash.Parse.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -44,7 +44,7 @@ public static Hash Parse(string value, HashAlgorithmType? type = null) /// A that contains a hash to convert. /// The hash algorithm type of the hash. /// The result if conversion was successful. - /// Returns true if the hash conversion was successful; otherwise, false. + /// Returns if the hash conversion was successful; otherwise, . public static bool TryParse(string value, HashAlgorithmType? type, out Hash hash) { try @@ -60,7 +60,7 @@ public static bool TryParse(string value, HashAlgorithmType? type, out Hash hash } /// - /// Parses a from the specified value. + /// Parses a from the specified value. /// /// The hash value to parse. /// Returns a from the specified value. diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs index d370b5c..1ce87d1 100644 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs +++ b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,7 +22,7 @@ public sealed partial class HashAlgorithmType /// Determines whether the length of a byte array is valid. /// /// The byte array to length check. - /// Returns true if the length of the byte array is valid; otherwise, false. + /// Returns if the length of the byte array is valid; otherwise, . public bool IsValidHashLength(byte[] value) { return Length == -1 || Length == value.Length; diff --git a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs index 3361ae5..303724f 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,7 +24,7 @@ namespace OnixLabs.Security.Cryptography; /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public bool Equals(Hmac other) { return other.Hash == Hash && other.Data.SequenceEqual(Data); @@ -34,7 +34,7 @@ public bool Equals(Hmac other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return obj is Hmac other && Equals(other); @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(Hmac left, Hmac right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(Hmac left, Hmac right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/Hmac.Parse.cs b/OnixLabs.Security.Cryptography/Hmac.Parse.cs index 281615f..6588073 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Parse.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Parse.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -42,7 +42,7 @@ public static Hmac Parse(string value, HashAlgorithmType? type = null) /// A that contains a HMAC to convert. /// The hash algorithm type of the hash. /// The result if conversion was successful. - /// Returns true if the hash conversion was successful; otherwise, false. + /// Returns if the hash conversion was successful; otherwise, . public static bool TryParse(string value, HashAlgorithmType? type, out Hmac hmac) { try diff --git a/OnixLabs.Security.Cryptography/Hmac.Verify.cs b/OnixLabs.Security.Cryptography/Hmac.Verify.cs index 3cb2407..baf4345 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Verify.cs +++ b/OnixLabs.Security.Cryptography/Hmac.Verify.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,7 +23,7 @@ public readonly partial struct Hmac /// Determines whether the hashed message authentication code (HMAC) was created with the specified key. /// /// The key to validate against this . - /// Returns true if this was created with the specified key; otherwise, false. + /// Returns if this was created with the specified key; otherwise, . public bool IsValid(string key) { return IsValid(key, Encoding.Default); @@ -34,7 +34,7 @@ public bool IsValid(string key) /// /// The key to validate against this . /// The encoding which will be used to convert the key into a byte array. - /// Returns true if this was created with the specified key; otherwise, false. + /// Returns if this was created with the specified key; otherwise, . public bool IsValid(string key, Encoding encoding) { byte[] keyBytes = encoding.GetBytes(key); @@ -45,7 +45,7 @@ public bool IsValid(string key, Encoding encoding) /// Determines whether the hashed message authentication code (HMAC) was created with the specified key. /// /// The key to validate against this . - /// Returns true if this was created with the specified key; otherwise, false. + /// Returns if this was created with the specified key; otherwise, . public bool IsValid(byte[] key) { return this == ComputeHmac(Data, key, Hash.AlgorithmType); diff --git a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs index f596d4c..6bcfa30 100644 --- a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs +++ b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,7 +22,7 @@ public sealed partial class KeyPair : IEquatable /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public bool Equals(KeyPair? other) { return ReferenceEquals(this, other) @@ -35,7 +35,7 @@ public bool Equals(KeyPair? other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as KeyPair); @@ -55,7 +55,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(KeyPair left, KeyPair right) { return Equals(left, right); @@ -66,7 +66,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(KeyPair left, KeyPair right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs b/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs index ba4f110..50e63c4 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,7 +22,7 @@ public abstract partial class MerkleTree : IEquatable /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public virtual bool Equals(MerkleTree? other) { return ReferenceEquals(this, other) || other is not null && other.Hash == Hash; @@ -32,7 +32,7 @@ public virtual bool Equals(MerkleTree? other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as MerkleTree); @@ -52,7 +52,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(MerkleTree left, MerkleTree right) { return Equals(left, right); @@ -63,7 +63,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(MerkleTree left, MerkleTree right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs index 6bde4b8..12ca814 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,7 +22,7 @@ public abstract partial class MerkleTree : IEquatable> /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public virtual bool Equals(MerkleTree? other) { return ReferenceEquals(this, other) || other is not null && other.Hash == Hash; @@ -32,7 +32,7 @@ public virtual bool Equals(MerkleTree? other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as MerkleTree); @@ -52,7 +52,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(MerkleTree left, MerkleTree right) { return Equals(left, right); @@ -63,7 +63,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(MerkleTree left, MerkleTree right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs b/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs index 6960d93..37369a6 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,7 +24,7 @@ public abstract partial class PrivateKey : IEquatable /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public virtual bool Equals(PrivateKey? other) { return ReferenceEquals(this, other) @@ -38,7 +38,7 @@ public virtual bool Equals(PrivateKey? other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as PrivateKey); @@ -58,7 +58,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(PrivateKey left, PrivateKey right) { return Equals(left, right); @@ -69,7 +69,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(PrivateKey left, PrivateKey right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs b/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs index 1aa3180..01e1599 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,7 +24,7 @@ public abstract partial class PublicKey : IEquatable /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public virtual bool Equals(PublicKey? other) { return ReferenceEquals(this, other) @@ -38,7 +38,7 @@ public virtual bool Equals(PublicKey? other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as PublicKey); @@ -58,7 +58,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(PublicKey left, PublicKey right) { return Equals(left, right); @@ -69,7 +69,7 @@ public override int GetHashCode() /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(PublicKey left, PublicKey right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/PublicKey.Verify.cs b/OnixLabs.Security.Cryptography/PublicKey.Verify.cs index 8831454..d1dee72 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.Verify.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,7 +23,7 @@ public abstract partial class PublicKey /// /// The to validate. /// The unsigned data to validate. - /// Returns true if the specified was signed by the private component of this public key; otherwise, false. + /// Returns if the specified was signed by the private component of this public key; otherwise, . public abstract bool IsDataValid(DigitalSignature signature, byte[] unsignedData); /// @@ -31,7 +31,7 @@ public abstract partial class PublicKey /// /// The to validate. /// The unsigned hash to validate. - /// Returns true if the specified was signed by the private component of this public key; otherwise, false. + /// Returns if the specified was signed by the private component of this public key; otherwise, . public abstract bool IsHashValid(DigitalSignature signature, byte[] unsignedHash); /// @@ -39,7 +39,7 @@ public abstract partial class PublicKey /// /// The to validate. /// The unsigned hash to validate. - /// Returns true if the specified was signed by the private component of this public key; otherwise, false. + /// Returns if the specified was signed by the private component of this public key; otherwise, . public bool IsHashValid(DigitalSignature signature, Hash unsignedHash) { byte[] unsignedHashBytes = unsignedHash.ToByteArray(); @@ -47,7 +47,7 @@ public bool IsHashValid(DigitalSignature signature, Hash unsignedHash) } /// - /// Verifies whether the specified was signed by the private component of this public key. + /// Verifies whether the specified was signed by the private component of this public key. /// /// The to verify. /// he unsigned data to verify. @@ -61,7 +61,7 @@ public void VerifyData(DigitalSignature signature, byte[] unsignedData) } /// - /// Verifies whether the specified was signed by the private component of this public key. + /// Verifies whether the specified was signed by the private component of this public key. /// /// The to verify. /// he unsigned hash to verify. @@ -75,7 +75,7 @@ public void VerifyHash(DigitalSignature signature, byte[] unsignedHash) } /// - /// Verifies whether the specified was signed by the private component of this public key. + /// Verifies whether the specified was signed by the private component of this public key. /// /// The to verify. /// he unsigned hash to verify. diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs index 38448ff..29af453 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,7 +20,7 @@ public sealed partial class RsaPrivateKey /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(PrivateKey? other) { return base.Equals(other) && other is RsaPrivateKey rsaOther && rsaOther.Padding == Padding; diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs index 3b290b2..d3bd821 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,7 +20,7 @@ public sealed partial class RsaPublicKey /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(PublicKey? other) { return base.Equals(other) && other is RsaPublicKey rsaOther && rsaOther.Padding == Padding; diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs index c131f33..c2895b8 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -23,7 +23,7 @@ public sealed partial class RsaPublicKey /// /// The to validate. /// The unsigned data to validate. - /// Returns true if the specified was signed by the private component of this public key; otherwise, false. + /// Returns if the specified was signed by the private component of this public key; otherwise, . public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData) { using RSA publicKey = RSA.Create(); @@ -38,7 +38,7 @@ public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData /// /// The to validate. /// The unsigned hash to validate. - /// Returns true if the specified was signed by the private component of this public key; otherwise, false. + /// Returns if the specified was signed by the private component of this public key; otherwise, . public override bool IsHashValid(DigitalSignature signature, byte[] unsignedHash) { using RSA publicKey = RSA.Create(); diff --git a/OnixLabs.Security.Cryptography/Salt.Equatable.cs b/OnixLabs.Security.Cryptography/Salt.Equatable.cs index e59e207..dd1d9fb 100644 --- a/OnixLabs.Security.Cryptography/Salt.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Salt.Equatable.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,7 +24,7 @@ namespace OnixLabs.Security.Cryptography; /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public bool Equals(Salt other) { return other.Value.SequenceEqual(Value); @@ -34,7 +34,7 @@ public bool Equals(Salt other) /// Checks for equality between this instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, false. + /// true if the object is equal to this instance; otherwise, . public override bool Equals(object? obj) { return obj is Salt other && Equals(other); @@ -54,7 +54,7 @@ public override int GetHashCode() /// /// Instance a. /// Instance b. - /// True if the instances are equal; otherwise, false. + /// True if the instances are equal; otherwise, . public static bool operator ==(Salt left, Salt right) { return Equals(left, right); @@ -65,7 +65,7 @@ public override int GetHashCode() /// /// Instance a. /// Instance b. - /// True if the instances are not equal; otherwise, false. + /// True if the instances are not equal; otherwise, . public static bool operator !=(Salt left, Salt right) { return !Equals(left, right); From ca98bb146aa72d974473789815e7345b5641f291 Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Sun, 5 May 2024 23:18:59 +0100 Subject: [PATCH 12/14] update/cleanup (#37) Code overhaul and cleanup including Core, Numerics and Cryptography libraries. --- .run/Build & Test.run.xml | 17 + .run/Run Playground.run.xml | 20 + .../{Objects => }/Color.cs | 10 +- .../Element.cs | 17 +- OnixLabs.Core.UnitTests.Data/Numeric.cs | 30 + .../Objects/Numeric.cs | 47 -- .../Objects/RecordLike.cs | 56 -- .../OnixLabs.Core.UnitTests.Data.csproj | 13 +- .../Record.cs | 12 +- .../ArrayExtensionTests.cs | 26 +- .../Collections/CollectionTests.cs | 401 ----------- OnixLabs.Core.UnitTests/EnumerationTests.cs | 10 +- .../Linq/IEnumerableExtensionTests.cs | 111 ++- .../ObjectExtensionTests.cs | 12 +- .../OnixLabs.Core.UnitTests.csproj | 5 +- OnixLabs.Core.UnitTests/PreconditionTests.cs | 21 +- .../Reflection/TypeExtensionTests.cs | 63 +- .../StringExtensionTests.cs | 8 +- .../Text/Base16CodecInvariantTests.cs | 58 ++ .../Text/Base16CodecLowercaseTests.cs | 58 ++ .../Text/Base16CodecUppercaseTests.cs | 58 ++ OnixLabs.Core.UnitTests/Text/Base16Tests.cs | 97 ++- .../Text/Base32Base32HexAlphabetTests.cs | 84 --- .../Text/Base32CodecBase32HexTests.cs | 58 ++ .../Text/Base32CodecCrockfordTests.cs | 58 ++ .../Text/Base32CodecGeoHashTests.cs | 58 ++ .../Text/Base32CodecPaddedBase32HexTests.cs | 58 ++ .../Text/Base32CodecPaddedCrockfordTests.cs | 58 ++ .../Text/Base32CodecPaddedGeoHashTests.cs | 58 ++ .../Text/Base32CodecPaddedRfc4648Tests.cs | 58 ++ .../Text/Base32CodecPaddedZBase32Tests.cs | 58 ++ .../Text/Base32CodecRfc4648Tests.cs | 58 ++ .../Text/Base32CodecZBase32Tests.cs | 58 ++ .../Text/Base32CrockfordAlphabetTests.cs | 84 --- .../Text/Base32DefaultAlphabetTests.cs | 84 --- OnixLabs.Core.UnitTests/Text/Base32Tests.cs | 119 ++++ .../Text/Base32ZBase32AlphabetTests.cs | 84 --- .../Text/Base58CodecBitcoinTests.cs | 58 ++ .../Text/Base58CodecFlickrTests.cs | 58 ++ ...abetTests.cs => Base58CodecRippleTests.cs} | 50 +- .../Text/Base58DefaultAlphabetTests.cs | 68 -- .../Text/Base58FlickrAlphabetTests.cs | 68 -- OnixLabs.Core.UnitTests/Text/Base58Tests.cs | 119 ++++ .../Text/Base64CodecTests.cs | 58 ++ OnixLabs.Core.UnitTests/Text/Base64Tests.cs | 91 ++- .../Text/StringBuilderExtensionTests.cs | 8 +- OnixLabs.Core/Collections/Collection.Empty.cs | 147 ---- OnixLabs.Core/Collections/Collection.Of.cs | 198 ------ OnixLabs.Core/Enumeration.Comparable.cs | 16 +- OnixLabs.Core/Enumeration.Equatable.cs | 16 +- OnixLabs.Core/Enumeration.From.cs | 8 +- OnixLabs.Core/Enumeration.Get.cs | 22 +- OnixLabs.Core/Enumeration.To.cs | 14 +- OnixLabs.Core/Enumeration.cs | 23 +- OnixLabs.Core/Extensions.Array.cs | 45 +- OnixLabs.Core/Extensions.Object.cs | 27 +- OnixLabs.Core/Extensions.String.cs | 379 +++++----- ...e16.Constants.cs => IBinaryConvertible.cs} | 19 +- OnixLabs.Core/IValueComparable.cs | 73 ++ OnixLabs.Core/IValueEquatable.cs | 40 ++ OnixLabs.Core/Linq/Extensions.IEnumerable.cs | 138 ++-- OnixLabs.Core/OnixLabs.Core.csproj | 3 +- OnixLabs.Core/Preconditions.cs | 63 +- OnixLabs.Core/Reflection/Extensions.Type.cs | 37 +- OnixLabs.Core/Text/Base16.Create.cs | 104 --- OnixLabs.Core/Text/Base16.Equatable.cs | 21 +- OnixLabs.Core/Text/Base16.Format.cs | 2 +- OnixLabs.Core/Text/Base16.Parse.cs | 71 +- OnixLabs.Core/Text/Base16.To.cs | 46 +- OnixLabs.Core/Text/Base16.cs | 20 +- OnixLabs.Core/Text/Base16Codec.cs | 143 ++++ OnixLabs.Core/Text/Base16FormatProvider.cs | 67 ++ OnixLabs.Core/Text/Base32.Create.cs | 104 --- OnixLabs.Core/Text/Base32.Equatable.cs | 21 +- OnixLabs.Core/Text/Base32.Format.cs | 2 +- OnixLabs.Core/Text/Base32.Parse.cs | 61 +- OnixLabs.Core/Text/Base32.To.cs | 46 +- OnixLabs.Core/Text/Base32.cs | 18 +- OnixLabs.Core/Text/Base32Codec.cs | 236 +++++-- OnixLabs.Core/Text/Base32FormatInfo.cs | 80 --- OnixLabs.Core/Text/Base32FormatProvider.cs | 107 +++ OnixLabs.Core/Text/Base58.Checksum.cs | 92 --- OnixLabs.Core/Text/Base58.Create.cs | 104 --- OnixLabs.Core/Text/Base58.Equatable.cs | 22 +- OnixLabs.Core/Text/Base58.Format.cs | 2 +- OnixLabs.Core/Text/Base58.Parse.cs | 126 +--- OnixLabs.Core/Text/Base58.To.cs | 45 +- OnixLabs.Core/Text/Base58.cs | 18 +- OnixLabs.Core/Text/Base58Codec.cs | 170 +++-- OnixLabs.Core/Text/Base58FormatInfo.cs | 67 -- OnixLabs.Core/Text/Base58FormatProvider.cs | 66 ++ OnixLabs.Core/Text/Base64.Create.cs | 104 --- OnixLabs.Core/Text/Base64.Equatable.cs | 21 +- OnixLabs.Core/Text/Base64.Format.cs | 2 +- OnixLabs.Core/Text/Base64.Parse.cs | 71 +- OnixLabs.Core/Text/Base64.To.cs | 44 +- OnixLabs.Core/Text/Base64.cs | 18 +- OnixLabs.Core/Text/Base64Codec.cs | 95 +++ ...ensions.cs => Extensions.StringBuilder.cs} | 2 +- OnixLabs.Core/Text/IBaseCodec.cs | 93 +++ OnixLabs.Core/Text/IBaseRepresentation.cs | 136 ---- OnixLabs.Core/Text/IBaseValue.cs | 43 ++ .../OnixLabs.Numerics.UnitTests.Data.csproj | 13 +- .../OnixLabs.Numerics.UnitTests.csproj | 15 +- .../BigDecimal.Comparable.MinMax.cs | 2 - OnixLabs.Numerics/BigDecimal.Convert.cs | 1 - .../BigDecimal.Convertible.Explicit.cs | 8 - OnixLabs.Numerics/BigDecimal.Convertible.cs | 3 +- OnixLabs.Numerics/BigDecimal.Equatable.cs | 2 - OnixLabs.Numerics/BigDecimal.cs | 3 +- OnixLabs.Numerics/NumberInfo.cs | 7 +- OnixLabs.Numerics/NumberInfoParser.cs | 2 +- OnixLabs.Numerics/OnixLabs.Numerics.csproj | 3 +- .../OnixLabs.Playground.csproj | 5 +- OnixLabs.Playground/Program.cs | 2 +- .../MerkleNode.cs | 26 +- .../Objects/MerkleNode.cs | 63 -- ...ecurity.Cryptography.UnitTests.Data.csproj | 13 +- .../TestPrivateKey.cs | 16 +- .../TestPublicKey.cs | 18 +- .../DigitalSignatureTests.cs | 123 ++++ .../EcdsaEncryptedPkcs8Tests.cs | 110 --- .../EcdsaKeyPkcs8Tests.cs | 100 --- .../EcdsaKeyTests.cs | 124 +--- .../HashAlgorithmExtensionTests.cs | 55 ++ .../HashAsyncTests.cs | 42 -- .../HashTests.cs | 429 ++++++++++-- .../HmacAsyncTests.cs | 53 -- .../HmacTests.cs | 83 --- .../KeyTestBase.cs | 30 - .../MerkleTreeGenericTests.cs | 68 +- .../MerkleTreeTests.cs | 49 +- ...abs.Security.Cryptography.UnitTests.csproj | 1 - .../PrivateKeyTests.cs | 124 ++++ .../PublicKeyTests.cs | 124 ++++ .../RsaKeyEncryptedPkcs8Tests.cs | 112 --- .../RsaKeyPkcs8Tests.cs | 104 --- .../RsaKeyTests.cs | 128 +--- .../SaltTests.cs | 123 +++- .../Sha3Hash224Tests.cs | 39 -- .../Sha3Hash256Tests.cs | 39 -- .../Sha3Hash384Tests.cs | 52 -- .../Sha3Hash512Tests.cs | 49 -- .../Sha3HashTestBase.cs | 44 -- .../Sha3Shake128Tests.cs | 54 -- .../Sha3Shake256Tests.cs | 54 -- .../Sha3ShakeTestBase.cs | 44 -- .../Sha3Tests.cs | 601 ++++++++++++++++ .../DigitalSignature.Constants.cs | 23 - .../DigitalSignature.Create.cs | 74 -- .../DigitalSignature.Equatable.cs | 31 +- .../DigitalSignature.To.cs | 51 +- .../DigitalSignature.Validation.cs | 94 --- .../DigitalSignature.cs | 29 +- .../EcdsaPrivateKey.Create.cs | 75 +- .../EcdsaPrivateKey.Export.cs | 30 +- .../EcdsaPrivateKey.Get.cs | 21 +- .../EcdsaPrivateKey.Import.cs | 125 ++-- .../EcdsaPrivateKey.Sign.cs | 150 +++- .../EcdsaPrivateKey.cs | 25 +- .../EcdsaPublicKey.Create.cs | 80 --- ....Equatable.cs => EcdsaPublicKey.Import.cs} | 17 +- .../EcdsaPublicKey.Verify.cs | 657 +++++++++++++++++- .../EcdsaPublicKey.cs | 25 +- .../Extensions.HashAlgorithm.cs | 103 +++ .../Hash.AllOneHash.cs | 55 -- .../Hash.AllZeroHash.cs | 55 -- .../Hash.Comparable.cs | 77 +- .../Hash.Compute.Md5Hash.cs | 52 -- .../Hash.Compute.Sha1Hash.cs | 52 -- .../Hash.Compute.Sha2Hash256.cs | 52 -- .../Hash.Compute.Sha2Hash384.cs | 52 -- .../Hash.Compute.Sha2Hash512.cs | 52 -- .../Hash.Compute.Sha3Hash224.cs | 52 -- .../Hash.Compute.Sha3Hash256.cs | 52 -- .../Hash.Compute.Sha3Hash384.cs | 52 -- .../Hash.Compute.Sha3Hash512.cs | 52 -- .../Hash.Compute.Sha3Shake128.cs | 55 -- .../Hash.Compute.Sha3Shake256.cs | 55 -- .../Hash.Compute.cs | 147 ++-- .../Hash.ComputeAsync.Md5Hash.cs | 53 -- .../Hash.ComputeAsync.Sha1Hash.cs | 53 -- .../Hash.ComputeAsync.Sha2Hash256.cs | 53 -- .../Hash.ComputeAsync.Sha2Hash384.cs | 53 -- .../Hash.ComputeAsync.Sha2Hash512.cs | 53 -- .../Hash.ComputeAsync.Sha3Hash224.cs | 53 -- .../Hash.ComputeAsync.Sha3Hash256.cs | 53 -- .../Hash.ComputeAsync.Sha3Hash384.cs | 53 -- .../Hash.ComputeAsync.Sha3Hash512.cs | 53 -- .../Hash.ComputeAsync.Sha3Shake128.cs | 56 -- .../Hash.ComputeAsync.Sha3Shake256.cs | 56 -- .../Hash.ComputeAsync.cs | 100 --- .../Hash.ComputeTwice.cs | 98 --- .../Hash.ComputeTwiceAsync.cs | 110 --- .../Hash.Concantenate.cs | 73 -- .../Hash.Concatenate.cs | 46 ++ OnixLabs.Security.Cryptography/Hash.Create.cs | 87 --- .../Hash.Equatable.cs | 31 +- OnixLabs.Security.Cryptography/Hash.Parse.cs | 99 --- OnixLabs.Security.Cryptography/Hash.To.cs | 60 +- OnixLabs.Security.Cryptography/Hash.cs | 34 +- .../HashAlgorithmType.Enumerations.cs | 103 --- .../HashAlgorithmType.Get.cs | 97 --- .../HashAlgorithmType.Verify.cs | 40 -- .../HashAlgorithmType.cs | 57 -- .../Hmac.Compute.Md5Hmac.cs | 57 -- .../Hmac.Compute.Sha1Hmac.cs | 57 -- .../Hmac.Compute.Sha2Hmac256.cs | 57 -- .../Hmac.Compute.Sha2Hmac384.cs | 57 -- .../Hmac.Compute.Sha2Hmac512.cs | 57 -- .../Hmac.Compute.cs | 63 -- .../Hmac.ComputeAsync.Md5Hmac.cs | 58 -- .../Hmac.ComputeAsync.Sha1Hmac.cs | 58 -- .../Hmac.ComputeAsync.Sha2Hmac256.cs | 58 -- .../Hmac.ComputeAsync.Sha2Hmac384.cs | 58 -- .../Hmac.ComputeAsync.Sha2Hmac512.cs | 58 -- .../Hmac.ComputeAsync.cs | 68 -- OnixLabs.Security.Cryptography/Hmac.Create.cs | 31 - .../Hmac.Equatable.cs | 73 -- OnixLabs.Security.Cryptography/Hmac.Parse.cs | 59 -- OnixLabs.Security.Cryptography/Hmac.To.cs | 38 - OnixLabs.Security.Cryptography/Hmac.Verify.cs | 85 --- OnixLabs.Security.Cryptography/Hmac.cs | 49 -- ...{Hmac.Constants.cs => ICryptoPrimitive.cs} | 22 +- .../IEcdsaPrivateKey.cs | 170 +++++ .../IEcdsaPublicKey.cs | 514 ++++++++++++++ OnixLabs.Security.Cryptography/IHashable.cs | 18 +- .../IRsaPrivateKey.cs | 134 ++++ .../IRsaPublicKey.cs | 322 +++++++++ .../KeyPair.Create.cs | 117 ---- .../KeyPair.Equatable.cs | 74 -- .../KeyPair.From.cs | 44 -- OnixLabs.Security.Cryptography/KeyPair.cs | 49 -- .../MerkleTree.Build.cs | 103 --- .../MerkleTree.Create.cs | 73 ++ .../MerkleTree.Equatable.cs | 32 +- .../MerkleTree.Generic.Build.cs | 83 --- .../MerkleTree.Generic.Create.cs | 62 ++ .../MerkleTree.Generic.Equatable.cs | 32 +- .../MerkleTree.Generic.Get.cs | 51 +- .../MerkleTree.Generic.cs | 66 +- .../MerkleTree.Get.cs | 25 +- .../MerkleTree.To.cs | 21 +- OnixLabs.Security.Cryptography/MerkleTree.cs | 47 +- .../OnixLabs.Security.Cryptography.csproj | 3 +- .../PrivateKey.Equatable.cs | 33 +- .../PrivateKey.Export.cs | 44 +- .../PrivateKey.Get.cs | 12 +- .../PrivateKey.Sign.cs | 43 -- .../PrivateKey.To.cs | 47 +- OnixLabs.Security.Cryptography/PrivateKey.cs | 36 +- .../PublicKey.Equatable.cs | 33 +- .../PublicKey.To.cs | 47 +- .../PublicKey.Verify.cs | 88 --- OnixLabs.Security.Cryptography/PublicKey.cs | 36 +- .../RsaPrivateKey.Create.cs | 76 +- .../RsaPrivateKey.Export.cs | 30 +- .../RsaPrivateKey.Get.cs | 23 +- .../RsaPrivateKey.Import.cs | 161 ++--- .../RsaPrivateKey.Sign.cs | 95 ++- .../RsaPrivateKey.cs | 32 +- .../RsaPublicKey.Create.cs | 85 --- ...ey.Equatable.cs => RsaPublicKey.Import.cs} | 15 +- .../RsaPublicKey.Verify.cs | 422 ++++++++++- .../RsaPublicKey.cs | 32 +- OnixLabs.Security.Cryptography/Salt.Create.cs | 26 +- .../Salt.Equatable.cs | 39 +- OnixLabs.Security.Cryptography/Salt.To.cs | 43 +- OnixLabs.Security.Cryptography/Salt.cs | 29 +- OnixLabs.Security.Cryptography/Sha3.Create.cs | 18 +- .../Sha3.Permute.cs | 14 +- OnixLabs.Security.Cryptography/Sha3.cs | 32 +- OnixLabs.Security.Cryptography/Sha3Hash224.cs | 8 +- OnixLabs.Security.Cryptography/Sha3Hash256.cs | 8 +- OnixLabs.Security.Cryptography/Sha3Hash384.cs | 8 +- OnixLabs.Security.Cryptography/Sha3Hash512.cs | 8 +- .../Sha3Shake128.cs | 8 +- .../Sha3Shake256.cs | 8 +- 278 files changed, 8325 insertions(+), 10244 deletions(-) create mode 100644 .run/Build & Test.run.xml create mode 100644 .run/Run Playground.run.xml rename OnixLabs.Core.UnitTests.Data/{Objects => }/Color.cs (90%) rename OnixLabs.Core/Text/Base58.Constants.cs => OnixLabs.Core.UnitTests.Data/Element.cs (68%) create mode 100644 OnixLabs.Core.UnitTests.Data/Numeric.cs delete mode 100644 OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs delete mode 100644 OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs rename OnixLabs.Core/Text/Base32.Constants.cs => OnixLabs.Core.UnitTests.Data/Record.cs (70%) delete mode 100644 OnixLabs.Core.UnitTests/Collections/CollectionTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base16CodecInvariantTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base16CodecLowercaseTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base16CodecUppercaseTests.cs delete mode 100644 OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecBase32HexTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecCrockfordTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecGeoHashTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecPaddedBase32HexTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecPaddedCrockfordTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecPaddedGeoHashTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecPaddedRfc4648Tests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecPaddedZBase32Tests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecRfc4648Tests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32CodecZBase32Tests.cs delete mode 100644 OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs delete mode 100644 OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base32Tests.cs delete mode 100644 OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base58CodecBitcoinTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base58CodecFlickrTests.cs rename OnixLabs.Core.UnitTests/Text/{Base58RippleAlphabetTests.cs => Base58CodecRippleTests.cs} (50%) delete mode 100644 OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs delete mode 100644 OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base58Tests.cs create mode 100644 OnixLabs.Core.UnitTests/Text/Base64CodecTests.cs delete mode 100644 OnixLabs.Core/Collections/Collection.Empty.cs delete mode 100644 OnixLabs.Core/Collections/Collection.Of.cs rename OnixLabs.Core/{Text/Base16.Constants.cs => IBinaryConvertible.cs} (55%) create mode 100644 OnixLabs.Core/IValueComparable.cs create mode 100644 OnixLabs.Core/IValueEquatable.cs delete mode 100644 OnixLabs.Core/Text/Base16.Create.cs create mode 100644 OnixLabs.Core/Text/Base16Codec.cs create mode 100644 OnixLabs.Core/Text/Base16FormatProvider.cs delete mode 100644 OnixLabs.Core/Text/Base32.Create.cs delete mode 100644 OnixLabs.Core/Text/Base32FormatInfo.cs create mode 100644 OnixLabs.Core/Text/Base32FormatProvider.cs delete mode 100644 OnixLabs.Core/Text/Base58.Checksum.cs delete mode 100644 OnixLabs.Core/Text/Base58.Create.cs delete mode 100644 OnixLabs.Core/Text/Base58FormatInfo.cs create mode 100644 OnixLabs.Core/Text/Base58FormatProvider.cs delete mode 100644 OnixLabs.Core/Text/Base64.Create.cs create mode 100644 OnixLabs.Core/Text/Base64Codec.cs rename OnixLabs.Core/Text/{StringBuilderExtensions.cs => Extensions.StringBuilder.cs} (99%) create mode 100644 OnixLabs.Core/Text/IBaseCodec.cs delete mode 100644 OnixLabs.Core/Text/IBaseRepresentation.cs create mode 100644 OnixLabs.Core/Text/IBaseValue.cs rename OnixLabs.Core.UnitTests.Data/Objects/Element.cs => OnixLabs.Security.Cryptography.UnitTests.Data/MerkleNode.cs (62%) delete mode 100644 OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs rename OnixLabs.Core/Text/Base64.Constants.cs => OnixLabs.Security.Cryptography.UnitTests.Data/TestPrivateKey.cs (56%) rename OnixLabs.Security.Cryptography/Hash.Constants.cs => OnixLabs.Security.Cryptography.UnitTests.Data/TestPublicKey.cs (68%) create mode 100644 OnixLabs.Security.Cryptography.UnitTests/DigitalSignatureTests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs create mode 100644 OnixLabs.Security.Cryptography.UnitTests/HashAlgorithmExtensionTests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs create mode 100644 OnixLabs.Security.Cryptography.UnitTests/PrivateKeyTests.cs create mode 100644 OnixLabs.Security.Cryptography.UnitTests/PublicKeyTests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs delete mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs create mode 100644 OnixLabs.Security.Cryptography.UnitTests/Sha3Tests.cs delete mode 100644 OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs delete mode 100644 OnixLabs.Security.Cryptography/DigitalSignature.Create.cs delete mode 100644 OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs delete mode 100644 OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs rename OnixLabs.Security.Cryptography/{RsaPrivateKey.Equatable.cs => EcdsaPublicKey.Import.cs} (58%) create mode 100644 OnixLabs.Security.Cryptography/Extensions.HashAlgorithm.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.AllOneHash.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Concantenate.cs create mode 100644 OnixLabs.Security.Cryptography/Hash.Concatenate.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Create.cs delete mode 100644 OnixLabs.Security.Cryptography/Hash.Parse.cs delete mode 100644 OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs delete mode 100644 OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs delete mode 100644 OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs delete mode 100644 OnixLabs.Security.Cryptography/HashAlgorithmType.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Compute.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Create.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Equatable.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Parse.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.To.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.Verify.cs delete mode 100644 OnixLabs.Security.Cryptography/Hmac.cs rename OnixLabs.Security.Cryptography/{Hmac.Constants.cs => ICryptoPrimitive.cs} (64%) create mode 100644 OnixLabs.Security.Cryptography/IEcdsaPrivateKey.cs create mode 100644 OnixLabs.Security.Cryptography/IEcdsaPublicKey.cs create mode 100644 OnixLabs.Security.Cryptography/IRsaPrivateKey.cs create mode 100644 OnixLabs.Security.Cryptography/IRsaPublicKey.cs delete mode 100644 OnixLabs.Security.Cryptography/KeyPair.Create.cs delete mode 100644 OnixLabs.Security.Cryptography/KeyPair.Equatable.cs delete mode 100644 OnixLabs.Security.Cryptography/KeyPair.From.cs delete mode 100644 OnixLabs.Security.Cryptography/KeyPair.cs delete mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Build.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Create.cs delete mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs create mode 100644 OnixLabs.Security.Cryptography/MerkleTree.Generic.Create.cs delete mode 100644 OnixLabs.Security.Cryptography/PrivateKey.Sign.cs delete mode 100644 OnixLabs.Security.Cryptography/PublicKey.Verify.cs delete mode 100644 OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs rename OnixLabs.Security.Cryptography/{RsaPublicKey.Equatable.cs => RsaPublicKey.Import.cs} (61%) diff --git a/.run/Build & Test.run.xml b/.run/Build & Test.run.xml new file mode 100644 index 0000000..35305ea --- /dev/null +++ b/.run/Build & Test.run.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.run/Run Playground.run.xml b/.run/Run Playground.run.xml new file mode 100644 index 0000000..611820d --- /dev/null +++ b/.run/Run Playground.run.xml @@ -0,0 +1,20 @@ + + + + \ No newline at end of file diff --git a/OnixLabs.Core.UnitTests.Data/Objects/Color.cs b/OnixLabs.Core.UnitTests.Data/Color.cs similarity index 90% rename from OnixLabs.Core.UnitTests.Data/Objects/Color.cs rename to OnixLabs.Core.UnitTests.Data/Color.cs index a254097..ec7f714 100644 --- a/OnixLabs.Core.UnitTests.Data/Objects/Color.cs +++ b/OnixLabs.Core.UnitTests.Data/Color.cs @@ -1,18 +1,18 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -namespace OnixLabs.Core.UnitTests.Data.Objects; +namespace OnixLabs.Core.UnitTests.Data; public sealed class Color : Enumeration { diff --git a/OnixLabs.Core/Text/Base58.Constants.cs b/OnixLabs.Core.UnitTests.Data/Element.cs similarity index 68% rename from OnixLabs.Core/Text/Base58.Constants.cs rename to OnixLabs.Core.UnitTests.Data/Element.cs index 62b1ff7..1066640 100644 --- a/OnixLabs.Core/Text/Base58.Constants.cs +++ b/OnixLabs.Core.UnitTests.Data/Element.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,15 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using System.Text; +namespace OnixLabs.Core.UnitTests.Data; -namespace OnixLabs.Core.Text; - -public readonly partial struct Base58 +public sealed class Element(int hashCode = 0) { - /// - /// Gets an empty value. - /// - public static Base58 Empty => new([]); + public bool Called { get; set; } + private int HashCode { get; } = hashCode; + + public override int GetHashCode() => HashCode; } diff --git a/OnixLabs.Core.UnitTests.Data/Numeric.cs b/OnixLabs.Core.UnitTests.Data/Numeric.cs new file mode 100644 index 0000000..dc20316 --- /dev/null +++ b/OnixLabs.Core.UnitTests.Data/Numeric.cs @@ -0,0 +1,30 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Numerics; + +namespace OnixLabs.Core.UnitTests.Data; + +public sealed class Numeric(T value) : IEquatable> where T : INumber +{ + public T Value { get; } = value; + + public bool Equals(Numeric? other) => other is not null && other.Value == Value; + + public override bool Equals(object? obj) => obj is Numeric other && Equals(other); + + public override int GetHashCode() => HashCode.Combine(Value); + + public override string ToString() => this.ToRecordString(); +} diff --git a/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs b/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs deleted file mode 100644 index 496f6b6..0000000 --- a/OnixLabs.Core.UnitTests.Data/Objects/Numeric.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Numerics; - -namespace OnixLabs.Core.UnitTests.Data.Objects; - -public sealed class Numeric : IEquatable> where T : INumber -{ - public Numeric(T value) - { - Value = value; - } - - public T Value { get; } - - public bool Equals(Numeric? other) - { - return other is not null && other.Value == Value; - } - - public override bool Equals(object? obj) - { - return obj is Numeric other && Equals(other); - } - - public override int GetHashCode() - { - return HashCode.Combine(Value); - } - - public override string ToString() - { - return this.ToRecordString(); - } -} diff --git a/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs b/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs deleted file mode 100644 index 8d95ff4..0000000 --- a/OnixLabs.Core.UnitTests.Data/Objects/RecordLike.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Core.UnitTests.Data.Objects; - -public sealed class RecordLike : IEquatable -{ - public RecordLike(string text, int number, DateTime moment, Guid identifier) - { - Text = text; - Number = number; - Moment = moment; - Identifier = identifier; - } - - public string Text { get; } - public int Number { get; } - public DateTime Moment { get; } - public Guid Identifier { get; } - - public bool Equals(RecordLike? other) - { - return ReferenceEquals(this, other) - || other is not null - && other.Text == Text - && other.Number == Number - && other.Moment == Moment - && other.Identifier == Identifier; - } - - public override bool Equals(object? obj) - { - return Equals(obj as RecordLike); - } - - public override int GetHashCode() - { - return HashCode.Combine(Text, Number, Moment, Identifier); - } - - public override string ToString() - { - return $"RecordLike {{ Text = {Text}, Number = {Number}, Moment = {Moment}, Identifier = {Identifier} }}"; - } -} diff --git a/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj b/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj index 6736305..da413fb 100644 --- a/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj +++ b/OnixLabs.Core.UnitTests.Data/OnixLabs.Core.UnitTests.Data.csproj @@ -1,5 +1,4 @@ - net8.0 enable @@ -9,10 +8,9 @@ 12 - - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -22,9 +20,10 @@ all - - + + + + - diff --git a/OnixLabs.Core/Text/Base32.Constants.cs b/OnixLabs.Core.UnitTests.Data/Record.cs similarity index 70% rename from OnixLabs.Core/Text/Base32.Constants.cs rename to OnixLabs.Core.UnitTests.Data/Record.cs index c0d9144..ff6927a 100644 --- a/OnixLabs.Core/Text/Base32.Constants.cs +++ b/OnixLabs.Core.UnitTests.Data/Record.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,12 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -namespace OnixLabs.Core.Text; +namespace OnixLabs.Core.UnitTests.Data; -public readonly partial struct Base32 -{ - /// - /// Gets an empty value. - /// - public static Base32 Empty => new([]); -} +public sealed record Record(string Text, int Number, T Value); diff --git a/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs b/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs index 32407cf..e53e0df 100644 --- a/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/ArrayExtensionTests.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -22,39 +22,39 @@ public sealed class ArrayExtensionTests public void CopyShouldProduceExpectedResult() { // Given - int[] array = { 1, 2, 3, 4, 5 }; - int[] expected = { 1, 2, 3, 4, 5 }; + int[] array = [1, 2, 3, 4, 5]; + int[] expected = [1, 2, 3, 4, 5]; // When int[] actual = array.Copy(); // Then Assert.Equal(expected, actual); - Assert.True(!ReferenceEquals(array, actual)); + Assert.False(ReferenceEquals(array, actual)); } [Fact(DisplayName = "Array.Copy with index and count parameters should produce a copy of an array")] public void CopyWithParametersShouldProduceExpectedResult() { // Given - int[] array = { 1, 2, 3, 4, 5 }; - int[] expected = { 3, 4, 5 }; + int[] array = [1, 2, 3, 4, 5]; + int[] expected = [3, 4, 5]; // When int[] actual = array.Copy(2, 3); // Then Assert.Equal(expected, actual); - Assert.True(!ReferenceEquals(array, actual)); + Assert.False(ReferenceEquals(array, actual)); } [Fact(DisplayName = "Array.ConcatenateWith should produce a concatenation of two arrays")] public void ConcatenateWithShouldProduceExpectedResult() { // Given - int[] left = { 1, 2, 3, 4, 5 }; - int[] right = { 6, 7, 8, 9, 10 }; - int[] expected = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int[] left = [1, 2, 3, 4, 5]; + int[] right = [6, 7, 8, 9, 10]; + int[] expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // When int[] actual = left.ConcatenateWith(right); diff --git a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs b/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs deleted file mode 100644 index 50a4d8b..0000000 --- a/OnixLabs.Core.UnitTests/Collections/CollectionTests.cs +++ /dev/null @@ -1,401 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using OnixLabs.Core.Collections; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Collections; - -public sealed class CollectionTests -{ - private static readonly object[] EnumerableInitializers = { true, false, 123, "abc", 1.23, true, false, 123, "abc", 1.23 }; - - private static readonly int[] NumericInitializers = { 123, 456, 789, 0, 1, -1, -987, 123, 456, 789, 0, 1, -1, -987 }; - - private static readonly KeyValuePair[] DictionaryInitializers = - { - new(123, true), - new("abc", null), - new(123.45f, "value") - }; - - private static readonly KeyValuePair[] SortedDictionaryInitializers = - { - new("key1", 123), - new("key2", false), - new("key3", "abc") - }; - - [Fact(DisplayName = "Collections.EmptyEnumerable should produce the expected result")] - public void CollectionsEmptyEnumerableShouldProduceTheExpectedResult() - { - // Given - IEnumerable candidate = EmptyEnumerable(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyArray should produce the expected result")] - public void CollectionsEmptyArrayShouldProduceTheExpectedResult() - { - // Given - object[] candidate = EmptyArray(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyImmutableArray should produce the expected result")] - public void CollectionsEmptyImmutableArrayShouldProduceTheExpectedResult() - { - // Given - ImmutableArray candidate = EmptyImmutableArray(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyList should produce the expected result")] - public void CollectionsEmptyListShouldProduceTheExpectedResult() - { - // Given - List candidate = EmptyList(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyImmutableList should produce the expected result")] - public void CollectionsEmptyImmutableListShouldProduceTheExpectedResult() - { - // Given - ImmutableList candidate = EmptyImmutableList(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyDictionary should produce the expected result")] - public void CollectionsEmptyDictionaryShouldProduceTheExpectedResult() - { - // Given - Dictionary candidate = EmptyDictionary(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyImmutableDictionary should produce the expected result")] - public void CollectionsEmptyImmutableDictionaryShouldProduceTheExpectedResult() - { - // Given - ImmutableDictionary candidate = EmptyImmutableDictionary(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptySortedDictionary should produce the expected result")] - public void CollectionsEmptySortedDictionaryShouldProduceTheExpectedResult() - { - // Given - SortedDictionary candidate = EmptySortedDictionary(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyImmutableSortedDictionary should produce the expected result")] - public void CollectionsEmptyImmutableSortedDictionaryShouldProduceTheExpectedResult() - { - // Given - ImmutableSortedDictionary candidate = EmptyImmutableSortedDictionary(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyHashSet should produce the expected result")] - public void CollectionsEmptyHashSetShouldProduceTheExpectedResult() - { - // Given - HashSet candidate = EmptyHashSet(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyImmutableHashSet should produce the expected result")] - public void CollectionsEmptyImmutableHashSetShouldProduceTheExpectedResult() - { - // Given - ImmutableHashSet candidate = EmptyImmutableHashSet(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptySortedSet should produce the expected result")] - public void CollectionsEmptySortedSetShouldProduceTheExpectedResult() - { - // Given - SortedSet candidate = EmptySortedSet(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyImmutableSortedSet should produce the expected result")] - public void CollectionsEmptyImmutableSortedSetShouldProduceTheExpectedResult() - { - // Given - ImmutableSortedSet candidate = EmptyImmutableSortedSet(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyStack should produce the expected result")] - public void CollectionsEmptyStackShouldProduceTheExpectedResult() - { - // Given - Stack candidate = EmptyStack(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyImmutableStack should produce the expected result")] - public void CollectionsEmptyImmutableStackShouldProduceTheExpectedResult() - { - // Given - ImmutableStack candidate = EmptyImmutableStack(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyQueue should produce the expected result")] - public void CollectionsEmptyQueueShouldProduceTheExpectedResult() - { - // Given - Queue candidate = EmptyQueue(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EmptyImmutableQueue should produce the expected result")] - public void CollectionsEmptyImmutableQueueShouldProduceTheExpectedResult() - { - // Given - ImmutableQueue candidate = EmptyImmutableQueue(); - - // Then - Assert.Empty(candidate); - } - - [Fact(DisplayName = "Collections.EnumerableOf should return the expected result")] - public void CollectionsEnumerableOfShouldReturnTheExpectedResult() - { - // Given - IEnumerable expected = EnumerableInitializers; - IEnumerable actual = EnumerableOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ArrayOf should return the expected result")] - public void CollectionsArrayOfShouldReturnTheExpectedResult() - { - // Given - object[] expected = EnumerableInitializers.ToArray(); - object[] actual = ArrayOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ImmutableArrayOf should return the expected result")] - public void CollectionsImmutableArrayOfShouldReturnTheExpectedResult() - { - // Given - ImmutableArray expected = ImmutableArray.Create(EnumerableInitializers); - ImmutableArray actual = ImmutableArrayOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ListOf should return the expected result")] - public void CollectionsListOfShouldReturnTheExpectedResult() - { - // Given - List expected = new(EnumerableInitializers); - List actual = ListOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ImmutableListOf should return the expected result")] - public void CollectionsImmutableListOfShouldReturnTheExpectedResult() - { - // Given - ImmutableList expected = ImmutableList.Create(EnumerableInitializers); - ImmutableList actual = ImmutableListOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.DictionaryOf should return the expected result")] - public void CollectionsDictionaryOfShouldReturnTheExpectedResult() - { - // Given - Dictionary expected = new(DictionaryInitializers); - Dictionary actual = DictionaryOf(DictionaryInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ImmutableDictionaryOf should return the expected result")] - public void CollectionsImmutableDictionaryOfShouldReturnTheExpectedResult() - { - // Given - ImmutableDictionary expected = new Dictionary(DictionaryInitializers).ToImmutableDictionary(); - ImmutableDictionary actual = ImmutableDictionaryOf(DictionaryInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.SortedDictionaryOf should return the expected result")] - public void CollectionsSortedDictionaryOfShouldReturnTheExpectedResult() - { - // Given - SortedDictionary expected = new(DictionaryOf(SortedDictionaryInitializers)); - SortedDictionary actual = SortedDictionaryOf(SortedDictionaryInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ImmutableSortedDictionaryOf should return the expected result")] - public void CollectionsImmutableSortedDictionaryOfShouldReturnTheExpectedResult() - { - // Given - SortedDictionary sorted = new(DictionaryOf(SortedDictionaryInitializers)); - ImmutableSortedDictionary expected = sorted.ToImmutableSortedDictionary(); - ImmutableSortedDictionary actual = ImmutableSortedDictionaryOf(SortedDictionaryInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.HashSetOf should return the expected result")] - public void CollectionsHashSetOfShouldReturnTheExpectedResult() - { - // Given - HashSet expected = new(EnumerableInitializers); - HashSet actual = HashSetOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ImmutableHashSetOf should return the expected result")] - public void CollectionsImmutableHashSetOfShouldReturnTheExpectedResult() - { - // Given - ImmutableHashSet expected = ImmutableHashSet.Create(EnumerableInitializers); - ImmutableHashSet actual = ImmutableHashSetOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.SortedSetOf should return the expected result")] - public void CollectionsSortedSetOfShouldReturnTheExpectedResult() - { - // Given - SortedSet expected = new(NumericInitializers); - SortedSet actual = SortedSetOf(NumericInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ImmutableSortedSetOf should return the expected result")] - public void CollectionsImmutableSortedSetOfShouldReturnTheExpectedResult() - { - // Given - ImmutableSortedSet expected = ImmutableSortedSet.Create(NumericInitializers); - ImmutableSortedSet actual = ImmutableSortedSetOf(NumericInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.StackOf should return the expected result")] - public void CollectionsStackOfShouldReturnTheExpectedResult() - { - // Given - Stack expected = new(EnumerableInitializers); - Stack actual = StackOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ImmutableStackOf should return the expected result")] - public void CollectionsImmutableStackOfShouldReturnTheExpectedResult() - { - // Given - ImmutableStack expected = ImmutableStack.Create(EnumerableInitializers); - ImmutableStack actual = ImmutableStackOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.QueueOf should return the expected result")] - public void CollectionsQueueOfShouldReturnTheExpectedResult() - { - // Given - Queue expected = new(EnumerableInitializers); - Queue actual = QueueOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } - - [Fact(DisplayName = "Collections.ImmutableQueueOf should return the expected result")] - public void CollectionsImmutableQueueOfShouldReturnTheExpectedResult() - { - // Given - ImmutableQueue expected = ImmutableQueue.Create(EnumerableInitializers); - ImmutableQueue actual = ImmutableQueueOf(EnumerableInitializers); - - // Then - Assert.True(expected.SequenceEqual(actual)); - } -} diff --git a/OnixLabs.Core.UnitTests/EnumerationTests.cs b/OnixLabs.Core.UnitTests/EnumerationTests.cs index cc6e166..5ed15a8 100644 --- a/OnixLabs.Core.UnitTests/EnumerationTests.cs +++ b/OnixLabs.Core.UnitTests/EnumerationTests.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -13,7 +13,7 @@ // limitations under the License. using System.Collections.Generic; -using OnixLabs.Core.UnitTests.Data.Objects; +using OnixLabs.Core.UnitTests.Data; using Xunit; namespace OnixLabs.Core.UnitTests; diff --git a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs index 5eeac5e..84280fe 100644 --- a/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/Linq/IEnumerableExtensionTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ using System.Globalization; using System.Linq; using OnixLabs.Core.Linq; -using OnixLabs.Core.UnitTests.Data.Objects; +using OnixLabs.Core.UnitTests.Data; using Xunit; namespace OnixLabs.Core.UnitTests.Linq; @@ -29,10 +29,10 @@ public sealed class IEnumerableExtensionTests public void AllEqualByShouldProduceExpectedResultTrue() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("abc", 123, Guid.NewGuid()); + Record element3 = new("abc", 123, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; // When bool result = elements.AllEqualBy(element => element.Text); @@ -45,10 +45,10 @@ public void AllEqualByShouldProduceExpectedResultTrue() public void AllEqualByShouldProduceExpectedResultFalse() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("xyz", 123, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("abc", 123, Guid.NewGuid()); + Record element3 = new("xyz", 123, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; // When bool result = elements.AllEqualBy(element => element.Text); @@ -61,10 +61,10 @@ public void AllEqualByShouldProduceExpectedResultFalse() public void AnyEqualByShouldProduceExpectedResultTrue() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("xyz", 123, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("abc", 123, Guid.NewGuid()); + Record element3 = new("xyz", 123, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; // When bool result = elements.AnyEqualBy(element => element.Text); @@ -77,10 +77,10 @@ public void AnyEqualByShouldProduceExpectedResultTrue() public void AnyEqualByShouldProduceExpectedResultFalse() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("def", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("xyz", 123, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("def", 123, Guid.NewGuid()); + Record element3 = new("xyz", 123, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; // When bool result = elements.AnyEqualBy(element => element.Text); @@ -93,10 +93,10 @@ public void AnyEqualByShouldProduceExpectedResultFalse() public void CountNotShouldProduceExpectedResult() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("def", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("xyz", 456, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("def", 123, Guid.NewGuid()); + Record element3 = new("xyz", 456, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; const int expected = 2; // When @@ -324,10 +324,10 @@ public void JoinToStringShouldProduceExpectedResultWithCustomSeparator() public void NoneShouldProduceExpectedResultTrue() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("def", 456, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("xyz", 789, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("def", 456, Guid.NewGuid()); + Record element3 = new("xyz", 789, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; // When bool result = elements.None(element => element.Number == 0); @@ -340,10 +340,10 @@ public void NoneShouldProduceExpectedResultTrue() public void NoneShouldProduceExpectedResultFalseAny() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("def", 456, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("xyz", 0, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("def", 456, Guid.NewGuid()); + Record element3 = new("xyz", 0, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; // When bool result = elements.None(element => element.Number == 0); @@ -356,10 +356,10 @@ public void NoneShouldProduceExpectedResultFalseAny() public void NoneShouldProduceExpectedResultFalseAll() { // Given - RecordLike element1 = new("abc", 0, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("def", 0, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("xyz", 0, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; + Record element1 = new("abc", 0, Guid.NewGuid()); + Record element2 = new("def", 0, Guid.NewGuid()); + Record element3 = new("xyz", 0, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; // When bool result = elements.None(element => element.Number == 0); @@ -372,8 +372,8 @@ public void NoneShouldProduceExpectedResultFalseAll() public void SumShouldProduceExpectedResult() { // Given - IEnumerable elements = ListOf(12.34m, 34.56m, 56.78m); - decimal expected = 103.68m; + IEnumerable elements = [12.34m, 34.56m, 56.78m]; + const decimal expected = 103.68m; // When decimal actual = elements.Sum(); @@ -389,8 +389,8 @@ public void SumWithSelectorShouldProduceExpectedResult() Numeric element1 = new(1234.567m); Numeric element2 = new(890.1234m); Numeric element3 = new(56.78901m); - IEnumerable> elements = ListOf(element1, element2, element3); - decimal expected = 2181.47941m; + IEnumerable> elements = [element1, element2, element3]; + const decimal expected = 2181.47941m; // When decimal actual = elements.SumBy(element => element.Value); @@ -399,31 +399,18 @@ public void SumWithSelectorShouldProduceExpectedResult() Assert.Equal(expected, actual); } - [Fact(DisplayName = "IEnumerable.WhereInstanceOf should return the correct elements matching the specified type")] - public void WhereInstanceOfShouldProduceExpectedResult() - { - // Given - IEnumerable enumerable = new object[] { 1, 2, 3, 4.5, true, false, Guid.NewGuid() }; - - // When - IEnumerable numbers = enumerable.WhereInstanceOf(); - - // Then - Assert.True(numbers.Count() == 3); - } - [Fact(DisplayName = "IEnumerable.WhereNot should produce the expected result")] public void WhereNotShouldProduceExpectedResult() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("def", 456, DateTime.Now, Guid.NewGuid()); - RecordLike element3 = new("xyz", 789, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, element3 }; - IEnumerable expected = new[] { element2, element3 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("def", 456, Guid.NewGuid()); + Record element3 = new("xyz", 789, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, element3 }; + IEnumerable> expected = new[] { element2, element3 }; // When - IEnumerable actual = elements.WhereNot(element => element.Number == 123); + IEnumerable> actual = elements.WhereNot(element => element.Number == 123); // Then Assert.Equal(expected, actual); @@ -433,13 +420,13 @@ public void WhereNotShouldProduceExpectedResult() public void WhereNotNullShouldProduceExpectedResult() { // Given - RecordLike element1 = new("abc", 123, DateTime.Now, Guid.NewGuid()); - RecordLike element2 = new("def", 456, DateTime.Now, Guid.NewGuid()); - IEnumerable elements = new[] { element1, element2, null }; - IEnumerable expected = new[] { element1, element2 }; + Record element1 = new("abc", 123, Guid.NewGuid()); + Record element2 = new("def", 456, Guid.NewGuid()); + IEnumerable> elements = new[] { element1, element2, null }; + IEnumerable> expected = new[] { element1, element2 }; // When - IEnumerable actual = elements.WhereNotNull(); + IEnumerable> actual = elements.WhereNotNull(); // Then Assert.Equal(expected, actual); diff --git a/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs b/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs index 25e5e3e..4492516 100644 --- a/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/ObjectExtensionTests.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -13,7 +13,7 @@ // limitations under the License. using System; -using OnixLabs.Core.UnitTests.Data.Objects; +using OnixLabs.Core.UnitTests.Data; using Xunit; namespace OnixLabs.Core.UnitTests; @@ -24,7 +24,7 @@ public sealed class ObjectExtensionTests public void ToRecordStringShouldProduceExpectedResult() { // Given - RecordLike record = new("abc", 123, DateTime.Now, Guid.NewGuid()); + Record record = new("abc", 123, Guid.NewGuid()); string expected = record.ToString(); // When diff --git a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj index c03520d..2a9f528 100644 --- a/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj +++ b/OnixLabs.Core.UnitTests/OnixLabs.Core.UnitTests.csproj @@ -5,8 +5,8 @@ 12 - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -22,6 +22,5 @@ - diff --git a/OnixLabs.Core.UnitTests/PreconditionTests.cs b/OnixLabs.Core.UnitTests/PreconditionTests.cs index e497f3d..0cb7b4b 100644 --- a/OnixLabs.Core.UnitTests/PreconditionTests.cs +++ b/OnixLabs.Core.UnitTests/PreconditionTests.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,7 +14,6 @@ using System; using Xunit; -using static OnixLabs.Core.Preconditions; namespace OnixLabs.Core.UnitTests; @@ -27,7 +26,7 @@ public void CheckShouldProduceExpectedResult() InvalidOperationException exception = Assert.Throws(() => Check(false)); // Then - Assert.Equal("Check requirement failed.", exception.Message); + Assert.Equal("Check failed.", exception.Message); } [Fact(DisplayName = "CheckNotNull should throw an ArgumentNullException when the condition is null")] @@ -50,6 +49,16 @@ public void RequireShouldProduceExpectedResult() Assert.Equal("Argument requirement failed.", exception.Message); } + [Fact(DisplayName = "RequireWithinRange should throw an ArgumentOutOfRangeException when the condition is false")] + public void RequireWithinRangeShouldProduceExpectedResult() + { + // When + ArgumentOutOfRangeException exception = Assert.Throws(() => RequireWithinRange(false)); + + // Then + Assert.Equal("Argument is out of range.", exception.Message); + } + [Fact(DisplayName = "RequireNotNull should throw an ArgumentNullException when the condition is null")] public void RequireNotNullShouldProduceExpectedResult() { diff --git a/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs b/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs index c08ae92..063e94d 100644 --- a/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/Reflection/TypeExtensionTests.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,57 +21,14 @@ namespace OnixLabs.Core.UnitTests.Reflection; public sealed class TypeExtensionTests { - [Fact(DisplayName = "Type.GetSimpleName from non-generic type should produce the expected type name")] - public void GetSimpleNameShouldProduceExpectedResultFromNonGenericType() + [Theory(DisplayName = "Type.GetName should produce the expected result")] + [InlineData(typeof(object), "Object")] + [InlineData(typeof(List<>), "List")] + [InlineData(typeof(Dictionary<,>), "Dictionary")] + public void TypeGetNameShouldProduceExpectedResult(Type type, string expected) { - // Given - Type type = typeof(object); - const string expected = "Object"; - - // When - string actual = type.GetSimpleName(); - - // Then - Assert.Equal(expected, actual); - } - - [Fact(DisplayName = "Type.GetSimpleName from generic type should produce the expected type name")] - public void GetSimpleNameShouldProduceExpectedResultFromGenericType() - { - // Given - Type type = typeof(Dictionary>); - const string expected = "Dictionary"; - - // When - string actual = type.GetSimpleName(); - - // Then - Assert.Equal(expected, actual); - } - - [Fact(DisplayName = "Type.GetFormattedName from non-generic type should produce the expected type name")] - public void GetFormattedNameShouldProduceExpectedResultFromNonGenericType() - { - // Given - Type type = typeof(object); - const string expected = "Object"; - - // When - string actual = type.GetFormattedName(); - - // Then - Assert.Equal(expected, actual); - } - - [Fact(DisplayName = "Type.GetFormattedName from generic type should produce the expected type name")] - public void GetFormattedNameShouldProduceExpectedResultFromGenericType() - { - // Given - Type type = typeof(Dictionary>); - const string expected = "Dictionary>"; - // When - string actual = type.GetFormattedName(); + string actual = type.GetName(); // Then Assert.Equal(expected, actual); diff --git a/OnixLabs.Core.UnitTests/StringExtensionTests.cs b/OnixLabs.Core.UnitTests/StringExtensionTests.cs index 0e6445e..aea70b5 100644 --- a/OnixLabs.Core.UnitTests/StringExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/StringExtensionTests.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/OnixLabs.Core.UnitTests/Text/Base16CodecInvariantTests.cs b/OnixLabs.Core.UnitTests/Text/Base16CodecInvariantTests.cs new file mode 100644 index 0000000..1e99222 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base16CodecInvariantTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base16CodecInvariantTests +{ + [Theory(DisplayName = "Base16Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","4142434445464748494a4b4c4d4e4f505152535455565758595a")] + [InlineData("abcdefghijklmnopqrstuvwxyz","6162636465666768696a6b6c6d6e6f707172737475767778797a")] + [InlineData("0123456789","30313233343536373839")] + public void Base16CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base16; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base16FormatProvider.Invariant); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base16Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("4142434445464748494a4b4c4d4e4f505152535455565758595a","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("6162636465666768696a6b6c6d6e6f707172737475767778797a","abcdefghijklmnopqrstuvwxyz")] + [InlineData("30313233343536373839","0123456789")] + public void Base16CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base16; + + // When + byte[] bytes = codec.Decode(value, Base16FormatProvider.Invariant); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base16CodecLowercaseTests.cs b/OnixLabs.Core.UnitTests/Text/Base16CodecLowercaseTests.cs new file mode 100644 index 0000000..a7a26c5 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base16CodecLowercaseTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base16CodecLowercaseTests +{ + [Theory(DisplayName = "Base16Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","4142434445464748494a4b4c4d4e4f505152535455565758595a")] + [InlineData("abcdefghijklmnopqrstuvwxyz","6162636465666768696a6b6c6d6e6f707172737475767778797a")] + [InlineData("0123456789","30313233343536373839")] + public void Base16CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base16; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base16FormatProvider.Lowercase); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base16Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("4142434445464748494a4b4c4d4e4f505152535455565758595a","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("6162636465666768696a6b6c6d6e6f707172737475767778797a","abcdefghijklmnopqrstuvwxyz")] + [InlineData("30313233343536373839","0123456789")] + public void Base16CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base16; + + // When + byte[] bytes = codec.Decode(value, Base16FormatProvider.Lowercase); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base16CodecUppercaseTests.cs b/OnixLabs.Core.UnitTests/Text/Base16CodecUppercaseTests.cs new file mode 100644 index 0000000..4176c93 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base16CodecUppercaseTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base16CodecUppercaseTests +{ + [Theory(DisplayName = "Base16Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","4142434445464748494A4B4C4D4E4F505152535455565758595A")] + [InlineData("abcdefghijklmnopqrstuvwxyz","6162636465666768696A6B6C6D6E6F707172737475767778797A")] + [InlineData("0123456789","30313233343536373839")] + public void Base16CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base16; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base16FormatProvider.Uppercase); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base16Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("4142434445464748494A4B4C4D4E4F505152535455565758595A","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("6162636465666768696A6B6C6D6E6F707172737475767778797A","abcdefghijklmnopqrstuvwxyz")] + [InlineData("30313233343536373839","0123456789")] + public void Base16CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base16; + + // When + byte[] bytes = codec.Decode(value, Base16FormatProvider.Uppercase); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base16Tests.cs b/OnixLabs.Core.UnitTests/Text/Base16Tests.cs index 1ec84cb..b7216ef 100644 --- a/OnixLabs.Core.UnitTests/Text/Base16Tests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base16Tests.cs @@ -1,17 +1,18 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System.Text; using OnixLabs.Core.Text; using Xunit; @@ -19,48 +20,98 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base16Tests { - [Fact(DisplayName = "Base16 values should be identical")] - public void Base16ValuesShouldBeIdentical() + [Fact(DisplayName = "Base16 should not change when modifying the original byte array")] + public void Base16ShouldNotChangeWhenModifyingOriginalByteArray() { // Given - Base16 a = Base16.Create("abcdefghijklmnopqrstuvwxyz"); - Base16 b = Base16.Create("abcdefghijklmnopqrstuvwxyz"); + byte[] bytes = "ABCabc123".ToByteArray(); + Base16 candidate = new(bytes); + const string expected = "414243616263313233"; // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); + bytes[0] = 0; + string actual = candidate.ToString(); // Then - Assert.Equal(hashCodeA, hashCodeB); + Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base16.Create should produce the expected Base-16 value")] - [InlineData("31323334353637383930", "1234567890")] - [InlineData("4142434445464748494a4b4c4d4e4f505152535455565758595a", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("6162636465666768696a6b6c6d6e6f707172737475767778797a", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResult(string expected, string value) + [Fact(DisplayName = "Base16 should not change when modifying the obtained byte array")] + public void Base16ShouldNotChangeWhenModifyingObtainedByteArray() { // Given - Base16 candidate = Base16.Create(value); + Base16 candidate = new("ABCabc123".ToByteArray()); + const string expected = "414243616263313233"; // When + byte[] bytes = candidate.ToByteArray(); + bytes[0] = 0; string actual = candidate.ToString(); // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base16.Parse should produce the expected plain text value")] - [InlineData("1234567890", "31323334353637383930")] - [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "4142434445464748494a4b4c4d4e4f505152535455565758595a")] - [InlineData("abcdefghijklmnopqrstuvwxyz", "6162636465666768696a6b6c6d6e6f707172737475767778797a")] - public void ParseShouldProduceExpectedResult(string expected, string value) + [Fact(DisplayName = "Base16 values should be identical")] + public void Base16ValuesShouldBeIdentical() + { + // Given + Base16 a = new([0, 255]); + Base16 b = new([0, 255]); + + // Then + Assert.Equal(a, b); + Assert.Equal(a.GetHashCode(), b.GetHashCode()); + Assert.True(a.Equals(b)); + Assert.True(a == b); + Assert.False(a != b); + } + + [Fact(DisplayName = "Base16 values should not be identical")] + public void Base16ValuesShouldNotBeIdentical() + { + // Given + Base16 a = new([0, 255]); + Base16 b = new([1, 127]); + + // Then + Assert.NotEqual(a, b); + Assert.NotEqual(a.GetHashCode(), b.GetHashCode()); + Assert.False(a.Equals(b)); + Assert.False(a == b); + Assert.True(a != b); + } + + [Theory(DisplayName = "Base16.Parse should produce the expected result")] + [InlineData("", "")] + [InlineData("4142434445464748494a4b4c4d4e4f505152535455565758595a","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("6162636465666768696a6b6c6d6e6f707172737475767778797a","abcdefghijklmnopqrstuvwxyz")] + [InlineData("30313233343536373839","0123456789")] + public void Base16ParseShouldProduceExpectedResult(string value, string expected) { // Given Base16 candidate = Base16.Parse(value); // When - string actual = candidate.ToPlainTextString(); + string actual = Encoding.UTF8.GetString(candidate.ToByteArray()); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base16.ToString should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","4142434445464748494a4b4c4d4e4f505152535455565758595a")] + [InlineData("abcdefghijklmnopqrstuvwxyz","6162636465666768696a6b6c6d6e6f707172737475767778797a")] + [InlineData("0123456789","30313233343536373839")] + public void Base16ToStringShouldProduceExpectedResult(string value, string expected) + { + // Given + byte[] bytes = Encoding.UTF8.GetBytes(value); + Base16 candidate = new(bytes); + + // When + string actual = candidate.ToString(); // Then Assert.Equal(expected, actual); diff --git a/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs deleted file mode 100644 index 2f80098..0000000 --- a/OnixLabs.Core.UnitTests/Text/Base32Base32HexAlphabetTests.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Text; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Text; - -public sealed class Base32Base32HexAlphabetTests -{ - [Fact(DisplayName = "Base32 values should be identical")] - public void Base32ValuesShouldBeIdentical() - { - // Given - Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz"); - Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz"); - - // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); - - // Then - Assert.Equal(hashCodeA, hashCodeB); - } - - [Theory(DisplayName = "Base32.Create with padding should produce the expected Base-32 value")] - [InlineData("64P36D1L6ORJGE9G", "1234567890")] - [InlineData("85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8======", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8======", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) - { - // Given - Base32 candidate = Base32.Create(value); - - // When - string actual = candidate.ToString("P", Base32FormatInfo.Base32Hex); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base32.Create without padding should produce the expected Base-32 value")] - [InlineData("64P36D1L6ORJGE9G", "1234567890")] - [InlineData("85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) - { - // Given - Base32 candidate = Base32.Create(value); - - // When - string actual = candidate.ToString(null, Base32FormatInfo.Base32Hex); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base32.Parse should produce the expected plain text value")] - [InlineData("1234567890", "64P36D1L6ORJGE9G")] - [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8")] - [InlineData("abcdefghijklmnopqrstuvwxyz", "C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8")] - public void ParseShouldProduceExpectedResult(string expected, string value) - { - // Given - Base32 candidate = Base32.Parse(value, Base32FormatInfo.Base32Hex); - - // When - string actual = candidate.ToPlainTextString(); - - // Then - Assert.Equal(expected, actual); - } -} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecBase32HexTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecBase32HexTests.cs new file mode 100644 index 0000000..a5abccb --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecBase32HexTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecBase32HexTests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8")] + [InlineData("abcdefghijklmnopqrstuvwxyz","C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8")] + [InlineData("0123456789","60OJ4CPK6KR3EE1P")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.Base32Hex); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8","abcdefghijklmnopqrstuvwxyz")] + [InlineData("60OJ4CPK6KR3EE1P","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.Base32Hex); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecCrockfordTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecCrockfordTests.cs new file mode 100644 index 0000000..b75133f --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecCrockfordTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecCrockfordTests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8")] + [InlineData("abcdefghijklmnopqrstuvwxyz","C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8")] + [InlineData("0123456789","60RK4CSM6MV3EE1S")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.Crockford); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8","abcdefghijklmnopqrstuvwxyz")] + [InlineData("60RK4CSM6MV3EE1S","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.Crockford); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecGeoHashTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecGeoHashTests.cs new file mode 100644 index 0000000..1aa3b0e --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecGeoHashTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecGeoHashTests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","85146j258t3nhkbb9e64umkgb18p4nunbpc5fq2tc8")] + [InlineData("abcdefghijklmnopqrstuvwxyz","d5j66t35dtmqhucbeeq6uvmgf1sr4wvnfpv7fy3tg8")] + [InlineData("0123456789","60sm4dtn6nv3ff1t")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.GeoHash); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("85146j258t3nhkbb9e64umkgb18p4nunbpc5fq2tc8","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("d5j66t35dtmqhucbeeq6uvmgf1sr4wvnfpv7fy3tg8","abcdefghijklmnopqrstuvwxyz")] + [InlineData("60sm4dtn6nv3ff1t","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.GeoHash); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedBase32HexTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedBase32HexTests.cs new file mode 100644 index 0000000..d1b68db --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedBase32HexTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecPaddedBase32HexTests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8======")] + [InlineData("abcdefghijklmnopqrstuvwxyz","C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8======")] + [InlineData("0123456789","60OJ4CPK6KR3EE1P")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.PaddedBase32Hex); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("85146H258P3KGIAA9D64QJIFA18L4KQKALB5EM2PB8======","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("C5H66P35CPJMGQBADDM6QRJFE1ON4SRKELR7EU3PF8======","abcdefghijklmnopqrstuvwxyz")] + [InlineData("60OJ4CPK6KR3EE1P","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.PaddedBase32Hex); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedCrockfordTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedCrockfordTests.cs new file mode 100644 index 0000000..ba48e0f --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedCrockfordTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecPaddedCrockfordTests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8======")] + [InlineData("abcdefghijklmnopqrstuvwxyz","C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8======")] + [InlineData("0123456789","60RK4CSM6MV3EE1S")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.PaddedCrockford); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8======","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8======","abcdefghijklmnopqrstuvwxyz")] + [InlineData("60RK4CSM6MV3EE1S","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.PaddedCrockford); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedGeoHashTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedGeoHashTests.cs new file mode 100644 index 0000000..07c820b --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedGeoHashTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecPaddedGeoHashTests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","85146j258t3nhkbb9e64umkgb18p4nunbpc5fq2tc8======")] + [InlineData("abcdefghijklmnopqrstuvwxyz","d5j66t35dtmqhucbeeq6uvmgf1sr4wvnfpv7fy3tg8======")] + [InlineData("0123456789","60sm4dtn6nv3ff1t")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.PaddedGeoHash); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("85146j258t3nhkbb9e64umkgb18p4nunbpc5fq2tc8======","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("d5j66t35dtmqhucbeeq6uvmgf1sr4wvnfpv7fy3tg8======","abcdefghijklmnopqrstuvwxyz")] + [InlineData("60sm4dtn6nv3ff1t","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.PaddedGeoHash); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedRfc4648Tests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedRfc4648Tests.cs new file mode 100644 index 0000000..da0ba10 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedRfc4648Tests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecPaddedRfc4648Tests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI======")] + [InlineData("abcdefghijklmnopqrstuvwxyz","MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI======")] + [InlineData("0123456789","GAYTEMZUGU3DOOBZ")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.PaddedRfc4648); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI======","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI======","abcdefghijklmnopqrstuvwxyz")] + [InlineData("GAYTEMZUGU3DOOBZ","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.PaddedRfc4648); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedZBase32Tests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedZBase32Tests.cs new file mode 100644 index 0000000..80838c9 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecPaddedZBase32Tests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecPaddedZBase32Tests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me======")] + [InlineData("abcdefghijklmnopqrstuvwxyz","cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe======")] + [InlineData("0123456789","gyaurc3wgw5dqqb3")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.PaddedZBase32); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me======","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe======","abcdefghijklmnopqrstuvwxyz")] + [InlineData("gyaurc3wgw5dqqb3","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.PaddedZBase32); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecRfc4648Tests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecRfc4648Tests.cs new file mode 100644 index 0000000..6a15981 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecRfc4648Tests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecRfc4648Tests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI")] + [InlineData("abcdefghijklmnopqrstuvwxyz","MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI")] + [InlineData("0123456789","GAYTEMZUGU3DOOBZ")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI","abcdefghijklmnopqrstuvwxyz")] + [InlineData("GAYTEMZUGU3DOOBZ","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CodecZBase32Tests.cs b/OnixLabs.Core.UnitTests/Text/Base32CodecZBase32Tests.cs new file mode 100644 index 0000000..23d1832 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32CodecZBase32Tests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32CodecZBase32Tests +{ + [Theory(DisplayName = "Base32Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me")] + [InlineData("abcdefghijklmnopqrstuvwxyz","cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe")] + [InlineData("0123456789","gyaurc3wgw5dqqb3")] + public void Base32CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base32FormatProvider.ZBase32); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe","abcdefghijklmnopqrstuvwxyz")] + [InlineData("gyaurc3wgw5dqqb3","0123456789")] + public void Base32CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base32; + + // When + byte[] bytes = codec.Decode(value, Base32FormatProvider.ZBase32); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs deleted file mode 100644 index e167b77..0000000 --- a/OnixLabs.Core.UnitTests/Text/Base32CrockfordAlphabetTests.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Text; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Text; - -public sealed class Base32CrockfordAlphabetTests -{ - [Fact(DisplayName = "Base32 values should be identical")] - public void Base32ValuesShouldBeIdentical() - { - // Given - Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz"); - Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz"); - - // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); - - // Then - Assert.Equal(hashCodeA, hashCodeB); - } - - [Theory(DisplayName = "Base32.Create with padding should produce the expected Base-32 value")] - [InlineData("64S36D1N6RVKGE9G", "1234567890")] - [InlineData("85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8======", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8======", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) - { - // Given - Base32 candidate = Base32.Create(value); - - // When - string actual = candidate.ToString("P", Base32FormatInfo.Crockford); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base32.Create without padding should produce the expected Base-32 value")] - [InlineData("64S36D1N6RVKGE9G", "1234567890")] - [InlineData("85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) - { - // Given - Base32 candidate = Base32.Create(value); - - // When - string actual = candidate.ToString(null, Base32FormatInfo.Crockford); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base32.Parse should produce the expected plain text value")] - [InlineData("1234567890", "64S36D1N6RVKGE9G")] - [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "85146H258S3MGJAA9D64TKJFA18N4MTMANB5EP2SB8")] - [InlineData("abcdefghijklmnopqrstuvwxyz", "C5H66S35CSKPGTBADDP6TVKFE1RQ4WVMENV7EY3SF8")] - public void ParseShouldProduceExpectedResult(string expected, string value) - { - // Given - Base32 candidate = Base32.Parse(value, Base32FormatInfo.Crockford); - - // When - string actual = candidate.ToPlainTextString(); - - // Then - Assert.Equal(expected, actual); - } -} diff --git a/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs deleted file mode 100644 index 2237989..0000000 --- a/OnixLabs.Core.UnitTests/Text/Base32DefaultAlphabetTests.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Text; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Text; - -public sealed class Base32DefaultAlphabetTests -{ - [Fact(DisplayName = "Base32 values should be identical")] - public void Base32ValuesShouldBeIdentical() - { - // Given - Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz"); - Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz"); - - // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); - - // Then - Assert.Equal(hashCodeA, hashCodeB); - } - - [Theory(DisplayName = "Base32.Create with padding should produce the expected Base-32 value")] - [InlineData("GEZDGNBVGY3TQOJQ", "1234567890")] - [InlineData("IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI======", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI======", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) - { - // Given - Base32 candidate = Base32.Create(value); - - // When - string actual = candidate.ToString("P", Base32FormatInfo.Default); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base32.Create without padding should produce the expected Base-32 value")] - [InlineData("GEZDGNBVGY3TQOJQ", "1234567890")] - [InlineData("IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) - { - // Given - Base32 candidate = Base32.Create(value); - - // When - string actual = candidate.ToString(null, Base32FormatInfo.Default); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base32.Parse should produce the expected plain text value")] - [InlineData("1234567890", "GEZDGNBVGY3TQOJQ")] - [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI")] - [InlineData("abcdefghijklmnopqrstuvwxyz", "MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI")] - public void ParseShouldProduceExpectedResult(string expected, string value) - { - // Given - Base32 candidate = Base32.Parse(value, Base32FormatInfo.Default); - - // When - string actual = candidate.ToPlainTextString(); - - // Then - Assert.Equal(expected, actual); - } -} diff --git a/OnixLabs.Core.UnitTests/Text/Base32Tests.cs b/OnixLabs.Core.UnitTests/Text/Base32Tests.cs new file mode 100644 index 0000000..5ff7d84 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base32Tests.cs @@ -0,0 +1,119 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base32Tests +{ + [Fact(DisplayName = "Base32 should not change when modifying the original byte array")] + public void Base32ShouldNotChangeWhenModifyingOriginalByteArray() + { + // Given + byte[] bytes = "ABCabc123".ToByteArray(); + Base32 candidate = new(bytes); + const string expected = "IFBEGYLCMMYTEMY"; + + // When + bytes[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Base32 should not change when modifying the obtained byte array")] + public void Base32ShouldNotChangeWhenModifyingObtainedByteArray() + { + // Given + Base32 candidate = new("ABCabc123".ToByteArray()); + const string expected = "IFBEGYLCMMYTEMY"; + + // When + byte[] bytes = candidate.ToByteArray(); + bytes[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Base32 values should be identical")] + public void Base32ValuesShouldBeIdentical() + { + // Given + Base32 a = new([0, 255]); + Base32 b = new([0, 255]); + + // Then + Assert.Equal(a, b); + Assert.Equal(a.GetHashCode(), b.GetHashCode()); + Assert.True(a.Equals(b)); + Assert.True(a == b); + Assert.False(a != b); + } + + [Fact(DisplayName = "Base32 values should not be identical")] + public void Base32ValuesShouldNotBeIdentical() + { + // Given + Base32 a = new([0, 255]); + Base32 b = new([1, 127]); + + // Then + Assert.NotEqual(a, b); + Assert.NotEqual(a.GetHashCode(), b.GetHashCode()); + Assert.False(a.Equals(b)); + Assert.False(a == b); + Assert.True(a != b); + } + + [Theory(DisplayName = "Base32.Parse should produce the expected result")] + [InlineData("", "")] + [InlineData("IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI","abcdefghijklmnopqrstuvwxyz")] + [InlineData("GAYTEMZUGU3DOOBZ","0123456789")] + public void Base32ParseShouldProduceExpectedResult(string value, string expected) + { + // Given + Base32 candidate = Base32.Parse(value); + + // When + string actual = Encoding.UTF8.GetString(candidate.ToByteArray()); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base32.ToString should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","IFBEGRCFIZDUQSKKJNGE2TSPKBIVEU2UKVLFOWCZLI")] + [InlineData("abcdefghijklmnopqrstuvwxyz","MFRGGZDFMZTWQ2LKNNWG23TPOBYXE43UOV3HO6DZPI")] + [InlineData("0123456789","GAYTEMZUGU3DOOBZ")] + public void Base32ToStringShouldProduceExpectedResult(string value, string expected) + { + // Given + byte[] bytes = Encoding.UTF8.GetBytes(value); + Base32 candidate = new(bytes); + + // When + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs deleted file mode 100644 index b48f0e8..0000000 --- a/OnixLabs.Core.UnitTests/Text/Base32ZBase32AlphabetTests.cs +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Text; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Text; - -public sealed class Base32ZBase32AlphabetTests -{ - [Fact(DisplayName = "Base32 values should be identical")] - public void Base32ValuesShouldBeIdentical() - { - // Given - Base32 a = Base32.Create("abcdefghijklmnopqrstuvwxyz"); - Base32 b = Base32.Create("abcdefghijklmnopqrstuvwxyz"); - - // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); - - // Then - Assert.Equal(hashCodeA, hashCodeB); - } - - [Theory(DisplayName = "Base32.Create with padding should produce the expected Base-32 value")] - [InlineData("gr3dgpbiga5uoqjo", "1234567890")] - [InlineData("efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me======", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe======", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResultWithPadding(string expected, string value) - { - // Given - Base32 candidate = Base32.Create(value); - - // When - string actual = candidate.ToString("P", Base32FormatInfo.ZBase32); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base32.Create without padding should produce the expected Base-32 value")] - [InlineData("gr3dgpbiga5uoqjo", "1234567890")] - [InlineData("efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResultWithoutPadding(string expected, string value) - { - // Given - Base32 candidate = Base32.Create(value); - - // When - string actual = candidate.ToString(null, Base32FormatInfo.ZBase32); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base32.Parse should produce the expected plain text value")] - [InlineData("1234567890", "gr3dgpbiga5uoqjo")] - [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "efbrgtnfe3dwo1kkjpgr4u1xkbeirw4wkimfqsn3me")] - [InlineData("abcdefghijklmnopqrstuvwxyz", "cftgg3dfc3uso4mkppsg45uxqbazrh5wqi58q6d3xe")] - public void ParseShouldProduceExpectedResult(string expected, string value) - { - // Given - Base32 candidate = Base32.Parse(value, Base32FormatInfo.ZBase32); - - // When - string actual = candidate.ToPlainTextString(); - - // Then - Assert.Equal(expected, actual); - } -} diff --git a/OnixLabs.Core.UnitTests/Text/Base58CodecBitcoinTests.cs b/OnixLabs.Core.UnitTests/Text/Base58CodecBitcoinTests.cs new file mode 100644 index 0000000..b0b0d1c --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base58CodecBitcoinTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base58CodecBitcoinTests +{ + [Theory(DisplayName = "Base58Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD")] + [InlineData("abcdefghijklmnopqrstuvwxyz","3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f")] + [InlineData("0123456789","3i37NcgooY8f1S")] + public void Base58CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base58; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base58FormatProvider.Bitcoin); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base58Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f","abcdefghijklmnopqrstuvwxyz")] + [InlineData("3i37NcgooY8f1S","0123456789")] + public void Base58CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base58; + + // When + byte[] bytes = codec.Decode(value, Base58FormatProvider.Bitcoin); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base58CodecFlickrTests.cs b/OnixLabs.Core.UnitTests/Text/Base58CodecFlickrTests.cs new file mode 100644 index 0000000..9e148fd --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base58CodecFlickrTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base58CodecFlickrTests +{ + [Theory(DisplayName = "Base58Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","2ZUfwsirsqj6erKTQGm2pdbKcMh1t46cMXzd")] + [InlineData("abcdefghijklmnopqrstuvwxyz","3YXt3U1HFx8vKFTJj92EAipcC4byHHs1V25E")] + [InlineData("0123456789","3H37nBFNNx8E1r")] + public void Base58CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base58; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes, Base58FormatProvider.Flickr); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base58Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("2ZUfwsirsqj6erKTQGm2pdbKcMh1t46cMXzd","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("3YXt3U1HFx8vKFTJj92EAipcC4byHHs1V25E","abcdefghijklmnopqrstuvwxyz")] + [InlineData("3H37nBFNNx8E1r","0123456789")] + public void Base58CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base58; + + // When + byte[] bytes = codec.Decode(value, Base58FormatProvider.Flickr); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58CodecRippleTests.cs similarity index 50% rename from OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs rename to OnixLabs.Core.UnitTests/Text/Base58CodecRippleTests.cs index b10067f..562835d 100644 --- a/OnixLabs.Core.UnitTests/Text/Base58RippleAlphabetTests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base58CodecRippleTests.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,55 +12,45 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.Text; using OnixLabs.Core.Text; using Xunit; namespace OnixLabs.Core.UnitTests.Text; -public sealed class Base58RippleAlphabetTests +public sealed class Base58CodecRippleTests { - [Fact(DisplayName = "Base58 values should be identical")] - public void Base58ValuesShouldBeIdentical() + [Theory(DisplayName = "Base58Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "pzuEXTJSTRKaNSktq6MpQDBkU8Hr7haU8x2D")] + [InlineData("abcdefghijklmnopqrstuvwxyz", "syx7sur5gY3WkgtjK9pCbJQUdhBZ55TrvpnC")] + [InlineData("0123456789", "s5sf4cgooY3CrS")] + public void Base58CodecEncodeShouldProduceExpectedResult(string value, string expected) { // Given - Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz"); - Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz"); + IBaseCodec codec = IBaseCodec.Base58; + byte[] bytes = value.ToByteArray(); // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); + string actual = codec.Encode(bytes, Base58FormatProvider.Ripple); // Then - Assert.Equal(hashCodeA, hashCodeB); + Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base58.Create should produce the expected Base-58 value")] - [InlineData("smJifwo7UHx4qd", "1234567890")] + [Theory(DisplayName = "Base58Codec.Decode should produce the expected result")] + [InlineData("", "")] [InlineData("pzuEXTJSTRKaNSktq6MpQDBkU8Hr7haU8x2D", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("syx7sur5gY3WkgtjK9pCbJQUdhBZ55TrvpnC", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResult(string expected, string value) - { - // Given - Base58 candidate = Base58.Create(value); - - // When - string actual = candidate.ToString(null, Base58FormatInfo.Ripple); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base58.Parse should produce the expected plain text value")] - [InlineData("1234567890", "smJifwo7UHx4qd")] - [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "pzuEXTJSTRKaNSktq6MpQDBkU8Hr7haU8x2D")] - [InlineData("abcdefghijklmnopqrstuvwxyz", "syx7sur5gY3WkgtjK9pCbJQUdhBZ55TrvpnC")] - public void ParseShouldProduceExpectedResult(string expected, string value) + [InlineData("s5sf4cgooY3CrS", "0123456789")] + public void Base58CodecDecodeShouldProduceExpectedResult(string value, string expected) { // Given - Base58 candidate = Base58.Parse(value, Base58FormatInfo.Ripple); + IBaseCodec codec = IBaseCodec.Base58; // When - string actual = candidate.ToPlainTextString(); + byte[] bytes = codec.Decode(value, Base58FormatProvider.Ripple); + string actual = Encoding.UTF8.GetString(bytes); // Then Assert.Equal(expected, actual); diff --git a/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs deleted file mode 100644 index db56568..0000000 --- a/OnixLabs.Core.UnitTests/Text/Base58DefaultAlphabetTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Text; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Text; - -public sealed class Base58DefaultAlphabetTests -{ - [Fact(DisplayName = "Base58 values should be identical")] - public void Base58ValuesShouldBeIdentical() - { - // Given - Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz"); - Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz"); - - // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); - - // Then - Assert.Equal(hashCodeA, hashCodeB); - } - - [Theory(DisplayName = "Base58.Create should produce the expected Base-58 value")] - [InlineData("3mJr7AoUCHxNqd", "1234567890")] - [InlineData("2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResult(string expected, string value) - { - // Given - Base58 candidate = Base58.Create(value); - - // When - string actual = candidate.ToString(null, Base58FormatInfo.Default); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base58.Parse should produce the expected plain text value")] - [InlineData("1234567890", "3mJr7AoUCHxNqd")] - [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD")] - [InlineData("abcdefghijklmnopqrstuvwxyz", "3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f")] - public void ParseShouldProduceExpectedResult(string expected, string value) - { - // Given - Base58 candidate = Base58.Parse(value, Base58FormatInfo.Default); - - // When - string actual = candidate.ToPlainTextString(); - - // Then - Assert.Equal(expected, actual); - } -} diff --git a/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs b/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs deleted file mode 100644 index 1a5698e..0000000 --- a/OnixLabs.Core.UnitTests/Text/Base58FlickrAlphabetTests.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Text; -using Xunit; - -namespace OnixLabs.Core.UnitTests.Text; - -public sealed class Base58FlickrAlphabetTests -{ - [Fact(DisplayName = "Base58 values should be identical")] - public void Base58ValuesShouldBeIdentical() - { - // Given - Base58 a = Base58.Create("abcdefghijklmnopqrstuvwxyz"); - Base58 b = Base58.Create("abcdefghijklmnopqrstuvwxyz"); - - // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); - - // Then - Assert.Equal(hashCodeA, hashCodeB); - } - - [Theory(DisplayName = "Base58.Create should produce the expected Base-58 value")] - [InlineData("3LiR7aNtchXnQC", "1234567890")] - [InlineData("2ZUfwsirsqj6erKTQGm2pdbKcMh1t46cMXzd", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("3YXt3U1HFx8vKFTJj92EAipcC4byHHs1V25E", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResult(string expected, string value) - { - // Given - Base58 candidate = Base58.Create(value); - - // When - string actual = candidate.ToString(null, Base58FormatInfo.Flickr); - - // Then - Assert.Equal(expected, actual); - } - - [Theory(DisplayName = "Base58.Parse should produce the expected plain text value")] - [InlineData("1234567890", "3LiR7aNtchXnQC")] - [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "2ZUfwsirsqj6erKTQGm2pdbKcMh1t46cMXzd")] - [InlineData("abcdefghijklmnopqrstuvwxyz", "3YXt3U1HFx8vKFTJj92EAipcC4byHHs1V25E")] - public void ParseShouldProduceExpectedResult(string expected, string value) - { - // Given - Base58 candidate = Base58.Parse(value, Base58FormatInfo.Flickr); - - // When - string actual = candidate.ToPlainTextString(); - - // Then - Assert.Equal(expected, actual); - } -} diff --git a/OnixLabs.Core.UnitTests/Text/Base58Tests.cs b/OnixLabs.Core.UnitTests/Text/Base58Tests.cs new file mode 100644 index 0000000..de00880 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base58Tests.cs @@ -0,0 +1,119 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base58Tests +{ + [Fact(DisplayName = "Base58 should not change when modifying the original byte array")] + public void Base58ShouldNotChangeWhenModifyingOriginalByteArray() + { + // Given + byte[] bytes = "ABCabc123".ToByteArray(); + Base58 candidate = new(bytes); + const string expected = "qBLgTCSW82Hg"; + + // When + bytes[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Base58 should not change when modifying the obtained byte array")] + public void Base58ShouldNotChangeWhenModifyingObtainedByteArray() + { + // Given + Base58 candidate = new("ABCabc123".ToByteArray()); + const string expected = "qBLgTCSW82Hg"; + + // When + byte[] bytes = candidate.ToByteArray(); + bytes[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Base58 values should be identical")] + public void Base58ValuesShouldBeIdentical() + { + // Given + Base58 a = new([0, 255]); + Base58 b = new([0, 255]); + + // Then + Assert.Equal(a, b); + Assert.Equal(a.GetHashCode(), b.GetHashCode()); + Assert.True(a.Equals(b)); + Assert.True(a == b); + Assert.False(a != b); + } + + [Fact(DisplayName = "Base58 values should not be identical")] + public void Base58ValuesShouldNotBeIdentical() + { + // Given + Base58 a = new([0, 255]); + Base58 b = new([1, 127]); + + // Then + Assert.NotEqual(a, b); + Assert.NotEqual(a.GetHashCode(), b.GetHashCode()); + Assert.False(a.Equals(b)); + Assert.False(a == b); + Assert.True(a != b); + } + + [Theory(DisplayName = "Base58.Parse should produce the expected result")] + [InlineData("", "")] + [InlineData("2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD","ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f","abcdefghijklmnopqrstuvwxyz")] + [InlineData("3i37NcgooY8f1S","0123456789")] + public void Base58ParseShouldProduceExpectedResult(string value, string expected) + { + // Given + Base58 candidate = Base58.Parse(value); + + // When + string actual = Encoding.UTF8.GetString(candidate.ToByteArray()); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base58.ToString should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ","2zuFXTJSTRK6ESktqhM2QDBkCnH1U46CnxaD")] + [InlineData("abcdefghijklmnopqrstuvwxyz","3yxU3u1igY8WkgtjK92fbJQCd4BZiiT1v25f")] + [InlineData("0123456789","3i37NcgooY8f1S")] + public void Base58ToStringShouldProduceExpectedResult(string value, string expected) + { + // Given + byte[] bytes = Encoding.UTF8.GetBytes(value); + Base58 candidate = new(bytes); + + // When + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base64CodecTests.cs b/OnixLabs.Core.UnitTests/Text/Base64CodecTests.cs new file mode 100644 index 0000000..fea69f2 --- /dev/null +++ b/OnixLabs.Core.UnitTests/Text/Base64CodecTests.cs @@ -0,0 +1,58 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Text; +using OnixLabs.Core.Text; +using Xunit; + +namespace OnixLabs.Core.UnitTests.Text; + +public sealed class Base64CodecTests +{ + [Theory(DisplayName = "Base64Codec.Encode should produce the expected result")] + [InlineData("", "")] + [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=")] + [InlineData("abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=")] + [InlineData("0123456789", "MDEyMzQ1Njc4OQ==")] + public void Base64CodecEncodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base64; + byte[] bytes = value.ToByteArray(); + + // When + string actual = codec.Encode(bytes); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Base64Codec.Decode should produce the expected result")] + [InlineData("", "")] + [InlineData("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] + [InlineData("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", "abcdefghijklmnopqrstuvwxyz")] + [InlineData("MDEyMzQ1Njc4OQ==", "0123456789")] + public void Base64CodecDecodeShouldProduceExpectedResult(string value, string expected) + { + // Given + IBaseCodec codec = IBaseCodec.Base64; + + // When + byte[] bytes = codec.Decode(value); + string actual = Encoding.UTF8.GetString(bytes); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Core.UnitTests/Text/Base64Tests.cs b/OnixLabs.Core.UnitTests/Text/Base64Tests.cs index 2eca15a..7b98b04 100644 --- a/OnixLabs.Core.UnitTests/Text/Base64Tests.cs +++ b/OnixLabs.Core.UnitTests/Text/Base64Tests.cs @@ -1,17 +1,18 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System.Text; using OnixLabs.Core.Text; using Xunit; @@ -19,48 +20,98 @@ namespace OnixLabs.Core.UnitTests.Text; public sealed class Base64Tests { + [Fact(DisplayName = "Base64 should not change when modifying the original byte array")] + public void Base64ShouldNotChangeWhenModifyingOriginalByteArray() + { + // Given + byte[] bytes = "ABCabc123".ToByteArray(); + Base64 candidate = new(bytes); + const string expected = "QUJDYWJjMTIz"; + + // When + bytes[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Base64 should not change when modifying the obtained byte array")] + public void Base64ShouldNotChangeWhenModifyingObtainedByteArray() + { + // Given + Base64 candidate = new("ABCabc123".ToByteArray()); + const string expected = "QUJDYWJjMTIz"; + + // When + byte[] bytes = candidate.ToByteArray(); + bytes[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + [Fact(DisplayName = "Base64 values should be identical")] public void Base64ValuesShouldBeIdentical() { // Given - Base64 a = Base64.Create("abcdefghijklmnopqrstuvwxyz"); - Base64 b = Base64.Create("abcdefghijklmnopqrstuvwxyz"); + Base64 a = new([0, 255]); + Base64 b = new([0, 255]); - // When - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); + // Then + Assert.Equal(a, b); + Assert.Equal(a.GetHashCode(), b.GetHashCode()); + Assert.True(a.Equals(b)); + Assert.True(a == b); + Assert.False(a != b); + } + + [Fact(DisplayName = "Base64 values should not be identical")] + public void Base64ValuesShouldNotBeIdentical() + { + // Given + Base64 a = new([0, 255]); + Base64 b = new([1, 127]); // Then - Assert.Equal(hashCodeA, hashCodeB); + Assert.NotEqual(a, b); + Assert.NotEqual(a.GetHashCode(), b.GetHashCode()); + Assert.False(a.Equals(b)); + Assert.False(a == b); + Assert.True(a != b); } - [Theory(DisplayName = "Base64.Create should produce the expected Base-64 value")] - [InlineData("MTIzNDU2Nzg5MA==", "1234567890")] + [Theory(DisplayName = "Base64.Parse should produce the expected result")] + [InlineData("", "")] [InlineData("QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] [InlineData("YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=", "abcdefghijklmnopqrstuvwxyz")] - public void CreateShouldProduceExpectedResult(string expected, string value) + [InlineData("MDEyMzQ1Njc4OQ==", "0123456789")] + public void Base64ParseShouldProduceExpectedResult(string value, string expected) { // Given - Base64 candidate = Base64.Create(value); + Base64 candidate = Base64.Parse(value); // When - string actual = candidate.ToString(); + string actual = Encoding.UTF8.GetString(candidate.ToByteArray()); // Then Assert.Equal(expected, actual); } - [Theory(DisplayName = "Base64.Parse should produce the expected plain text value")] - [InlineData("1234567890", "MTIzNDU2Nzg5MA==")] + [Theory(DisplayName = "Base64.ToString should produce the expected result")] + [InlineData("", "")] [InlineData("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVo=")] [InlineData("abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=")] - public void ParseShouldProduceExpectedResult(string expected, string value) + [InlineData("0123456789", "MDEyMzQ1Njc4OQ==")] + public void Base64ToStringShouldProduceExpectedResult(string value, string expected) { // Given - Base64 candidate = Base64.Parse(value); + byte[] bytes = Encoding.UTF8.GetBytes(value); + Base64 candidate = new(bytes); // When - string actual = candidate.ToPlainTextString(); + string actual = candidate.ToString(); // Then Assert.Equal(expected, actual); diff --git a/OnixLabs.Core.UnitTests/Text/StringBuilderExtensionTests.cs b/OnixLabs.Core.UnitTests/Text/StringBuilderExtensionTests.cs index 815d442..868765d 100644 --- a/OnixLabs.Core.UnitTests/Text/StringBuilderExtensionTests.cs +++ b/OnixLabs.Core.UnitTests/Text/StringBuilderExtensionTests.cs @@ -1,11 +1,11 @@ -// Copyright 2020-2023 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/OnixLabs.Core/Collections/Collection.Empty.cs b/OnixLabs.Core/Collections/Collection.Empty.cs deleted file mode 100644 index 53c8fce..0000000 --- a/OnixLabs.Core/Collections/Collection.Empty.cs +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Collections.Generic; -using System.Collections.Immutable; - -namespace OnixLabs.Core.Collections; - -/// -/// Provides methods to create empty or populated mutable and immutable collections. -/// -public static partial class Collection -{ - /// - /// Creates an empty enumerable. - /// - /// The underlying type of the enumerable. - /// Returns an empty enumerable. - public static IEnumerable EmptyEnumerable() => []; - - /// - /// Creates an empty array. - /// - /// The underlying type of the array. - /// Returns an empty array. - public static T[] EmptyArray() => []; - - /// - /// Creates an empty immutable array. - /// - /// The underlying type of the immutable array. - /// Returns an empty immutable array. - public static ImmutableArray EmptyImmutableArray() => []; - - /// - /// Creates an empty list. - /// - /// The underlying type of the list. - /// Returns an empty list. - public static List EmptyList() => []; - - /// - /// Creates an empty immutable list. - /// - /// The underlying type of the immutable list. - /// Returns an empty immutable list. - public static ImmutableList EmptyImmutableList() => []; - - /// - /// Creates an empty dictionary. - /// - /// The underlying type of the dictionary key. - /// The underlying type of the dictionary value. - /// Returns an empty dictionary. - public static Dictionary EmptyDictionary() where TKey : notnull => []; - - /// - /// Creates an empty immutable dictionary. - /// - /// The underlying type of the immutable dictionary key. - /// The underlying type of the immutable dictionary value. - /// Returns an empty immutable dictionary. - public static ImmutableDictionary EmptyImmutableDictionary() where TKey : notnull => ImmutableDictionary.Empty; - - /// - /// Creates an empty sorted dictionary. - /// - /// The underlying type of the sorted dictionary key. - /// The underlying type of the sorted dictionary value. - /// Returns an empty sorted dictionary. - public static SortedDictionary EmptySortedDictionary() where TKey : notnull => []; - - /// - /// Creates an empty immutable sorted dictionary. - /// - /// The underlying type of the immutable sorted dictionary key. - /// The underlying type of the immutable sorted dictionary value. - /// Returns an empty immutable sorted dictionary. - public static ImmutableSortedDictionary EmptyImmutableSortedDictionary() where TKey : notnull => ImmutableSortedDictionary.Empty; - - /// - /// Creates an empty hash set. - /// - /// The underlying type of the hash set. - /// Returns an empty hash set. - public static HashSet EmptyHashSet() => []; - - /// - /// Creates an empty immutable hash set. - /// - /// The underlying type of the immutable hash set. - /// Returns an empty immutable hash set. - public static ImmutableHashSet EmptyImmutableHashSet() => []; - - /// - /// Creates an empty sorted set. - /// - /// The underlying type of the sorted set. - /// Returns an empty sorted set. - public static SortedSet EmptySortedSet() => []; - - /// - /// Creates an empty immutable sorted set. - /// - /// The underlying type of the immutable sorted set. - /// Returns an empty immutable sorted set. - public static ImmutableSortedSet EmptyImmutableSortedSet() => []; - - /// - /// Creates an empty stack. - /// - /// The underlying type of the stack. - /// Returns an empty stack. - public static Stack EmptyStack() => []; - - /// - /// Creates an empty immutable stack. - /// - /// The underlying type of the immutable stack. - /// Returns an empty immutable stack. - public static ImmutableStack EmptyImmutableStack() => []; - - /// - /// Creates an empty queue. - /// - /// The underlying type of the queue. - /// Returns an empty queue. - public static Queue EmptyQueue() => []; - - /// - /// Creates an empty immutable queue. - /// - /// The underlying type of the immutable queue. - /// Returns an empty immutable queue. - public static ImmutableQueue EmptyImmutableQueue() => []; -} diff --git a/OnixLabs.Core/Collections/Collection.Of.cs b/OnixLabs.Core/Collections/Collection.Of.cs deleted file mode 100644 index 1710a4e..0000000 --- a/OnixLabs.Core/Collections/Collection.Of.cs +++ /dev/null @@ -1,198 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; - -namespace OnixLabs.Core.Collections; - -public static partial class Collection -{ - /// - /// Creates an enumerable of the specified items. - /// - /// The items which will populate the enumerable. - /// The underlying type of the enumerable. - /// Returns an enumerable populated with the specified items. - public static IEnumerable EnumerableOf(params T[] items) => [..items]; - - /// - /// Creates an array of the specified items. - /// - /// The items which will populate the array. - /// The underlying type of the array. - /// Returns an array populated with the specified items. - public static T[] ArrayOf(params T[] items) => [..items]; - - /// - /// Creates an immutable array of the specified items. - /// - /// The items which will populate the immutable array. - /// The underlying type of the immutable array. - /// Returns an immutable array populated with the specified items. - public static ImmutableArray ImmutableArrayOf(params T[] items) => [..items]; - - /// - /// Creates a list of the specified items. - /// - /// The items which will populate the list. - /// The underlying type of the list. - /// Returns a list populated with the specified items. - public static List ListOf(params T[] items) => [..items]; - - /// - /// Creates an immutable list of the specified items. - /// - /// The items which will populate the immutable list. - /// The underlying type of the immutable list. - /// Returns an immutable list populated with the specified items. - public static ImmutableList ImmutableListOf(params T[] items) => [..items]; - - /// - /// Create a dictionary of the specified items. - /// - /// The items which wil populate the dictionary. - /// The underlying type of the dictionary key. - /// The underlying type of the dictionary value. - /// Returns a dictionary populated with the specified items. - public static Dictionary DictionaryOf(params KeyValuePair[] items) where TKey : notnull => new(items); - - /// - /// Create a dictionary of the specified items. - /// - /// The items which wil populate the dictionary. - /// The underlying type of the dictionary key. - /// The underlying type of the dictionary value. - /// Returns a dictionary populated with the specified items. - public static Dictionary DictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull => DictionaryOf(items.Select(item => new KeyValuePair(item.key, item.value)).ToArray()); - - /// - /// Create an immutable dictionary of the specified items. - /// - /// The items which wil populate the immutable dictionary. - /// The underlying type of the immutable dictionary key. - /// The underlying type of the immutable dictionary value. - /// Returns an immutable dictionary populated with the specified items. - public static ImmutableDictionary ImmutableDictionaryOf(params KeyValuePair[] items) where TKey : notnull => ImmutableDictionary.CreateRange(items); - - /// - /// Create an immutable dictionary of the specified items. - /// - /// The items which wil populate the immutable dictionary. - /// The underlying type of the immutable dictionary key. - /// The underlying type of the immutable dictionary value. - /// Returns an immutable dictionary populated with the specified items. - public static ImmutableDictionary ImmutableDictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull => ImmutableDictionary.CreateRange(items.Select(item => new KeyValuePair(item.key, item.value))); - - /// - /// Create a sorted dictionary of the specified items. - /// - /// The items which wil populate the sorted dictionary. - /// The underlying type of the sorted dictionary key. - /// The underlying type of the sorted dictionary value. - /// Returns a sorted dictionary populated with the specified items. - public static SortedDictionary SortedDictionaryOf(params KeyValuePair[] items) where TKey : notnull => new(DictionaryOf(items)); - - /// - /// Create a sorted dictionary of the specified items. - /// - /// The items which wil populate the sorted dictionary. - /// The underlying type of the sorted dictionary key. - /// The underlying type of the sorted dictionary value. - /// Returns a sorted dictionary populated with the specified items. - public static SortedDictionary SortedDictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull => new(DictionaryOf(items)); - - /// - /// Create an immutable sorted dictionary of the specified items. - /// - /// The items which wil populate the immutable sorted dictionary. - /// The underlying type of the immutable sorted dictionary key. - /// The underlying type of the immutable sorted dictionary value. - /// Returns an immutable sorted dictionary populated with the specified items. - public static ImmutableSortedDictionary ImmutableSortedDictionaryOf(params KeyValuePair[] items) where TKey : notnull => ImmutableSortedDictionary.CreateRange(items); - - /// - /// Create an immutable sorted dictionary of the specified items. - /// - /// The items which wil populate the immutable sorted dictionary. - /// The underlying type of the immutable sorted dictionary key. - /// The underlying type of the immutable sorted dictionary value. - /// Returns an immutable sorted dictionary populated with the specified items. - public static ImmutableSortedDictionary ImmutableSortedDictionaryOf(params (TKey key, TValue value)[] items) where TKey : notnull => ImmutableSortedDictionary.CreateRange(items.Select(item => new KeyValuePair(item.key, item.value))); - - /// - /// Creates a hash set of the specified items. - /// - /// The items which will populate the hash set. - /// The underlying type of the hash set. - /// Returns a hash set populated with the specified items. - public static HashSet HashSetOf(params T[] items) => [..items]; - - /// - /// Creates an immutable hash set of the specified items. - /// - /// The items which will populate the immutable hash set. - /// The underlying type of the immutable hash set. - /// Returns an immutable hash set populated with the specified items. - public static ImmutableHashSet ImmutableHashSetOf(params T[] items) => [..items]; - - /// - /// Creates a sorted set of the specified items. - /// - /// The items which will populate the sorted set. - /// The underlying type of the sorted set. - /// Returns a sorted set populated with the specified items. - public static SortedSet SortedSetOf(params T[] items) => [..items]; - - /// - /// Creates an immutable sorted set of the specified items. - /// - /// The items which will populate the immutable sorted set. - /// The underlying type of the immutable sorted set. - /// Returns an immutable sorted set populated with the specified items. - public static ImmutableSortedSet ImmutableSortedSetOf(params T[] items) => [..items]; - - /// - /// Creates a stack of the specified items. - /// - /// The items which will populate the stack. - /// The underlying type of the stack. - /// Returns a stack populated with the specified items. - public static Stack StackOf(params T[] items) => new(items); - - /// - /// Creates an immutable stack of the specified items. - /// - /// The items which will populate the immutable stack. - /// The underlying type of the immutable stack. - /// Returns an immutable stack populated with the specified items. - public static ImmutableStack ImmutableStackOf(params T[] items) => [..items]; - - /// - /// Creates a queue of the specified items. - /// - /// The items which will populate the queue. - /// The underlying type of the queue. - /// Returns a queue populated with the specified items. - public static Queue QueueOf(params T[] items) => new(items); - - /// - /// Creates an immutable queue of the specified items. - /// - /// The items which will populate the immutable queue. - /// The underlying type of the immutable queue. - /// Returns an immutable queue populated with the specified items. - public static ImmutableQueue ImmutableQueueOf(params T[] items) => [..items]; -} diff --git a/OnixLabs.Core/Enumeration.Comparable.cs b/OnixLabs.Core/Enumeration.Comparable.cs index a850d61..8275d76 100644 --- a/OnixLabs.Core/Enumeration.Comparable.cs +++ b/OnixLabs.Core/Enumeration.Comparable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; - namespace OnixLabs.Core; public abstract partial class Enumeration @@ -23,11 +21,11 @@ public abstract partial class Enumeration /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the /// other object. /// - /// An object to compare with the current instance. + /// An object to compare with the current instance. /// Returns a value that indicates the relative order of the objects being compared. - public int CompareTo(object? obj) + public int CompareTo(T? other) { - return this.CompareObject(obj); + return Value.CompareTo(other?.Value); } /// @@ -35,10 +33,10 @@ public int CompareTo(object? obj) /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the /// other object. /// - /// An object to compare with the current instance. + /// An object to compare with the current instance. /// Returns a value that indicates the relative order of the objects being compared. - public int CompareTo(T? other) + public int CompareTo(object? obj) { - return Value.CompareTo(other?.Value); + return this.CompareToObject(obj); } } diff --git a/OnixLabs.Core/Enumeration.Equatable.cs b/OnixLabs.Core/Enumeration.Equatable.cs index 90e3d49..0cb68f1 100644 --- a/OnixLabs.Core/Enumeration.Equatable.cs +++ b/OnixLabs.Core/Enumeration.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ namespace OnixLabs.Core; public abstract partial class Enumeration { /// - /// Indicates whether the current object is equal to another object of the same type. + /// Checks whether the current object is equal to another object of the same type. /// /// An object to compare with the current object. /// Returns if the current object is equal to the other parameter; otherwise, . @@ -37,7 +37,7 @@ public bool Equals(T? other) /// /// The object to check for equality. /// Returns if the object is equal to the current instance; otherwise, . - public sealed override bool Equals(object? obj) + public override bool Equals(object? obj) { return Equals(obj as T); } @@ -46,28 +46,28 @@ public sealed override bool Equals(object? obj) /// Serves as a hash code function for the current instance. /// /// Returns a hash code for the current instance. - public sealed override int GetHashCode() + public override int GetHashCode() { return HashCode.Combine(GetType(), Name, Value); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(Enumeration left, Enumeration right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(Enumeration left, Enumeration right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Enumeration.From.cs b/OnixLabs.Core/Enumeration.From.cs index 7846f24..467e18c 100644 --- a/OnixLabs.Core/Enumeration.From.cs +++ b/OnixLabs.Core/Enumeration.From.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. diff --git a/OnixLabs.Core/Enumeration.Get.cs b/OnixLabs.Core/Enumeration.Get.cs index a7e3af8..8acee6d 100644 --- a/OnixLabs.Core/Enumeration.Get.cs +++ b/OnixLabs.Core/Enumeration.Get.cs @@ -1,26 +1,24 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System.Collections.Frozen; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; using System.Reflection; -using OnixLabs.Core.Linq; namespace OnixLabs.Core; -// ReSharper disable ReturnTypeCanBeEnumerable.Global public abstract partial class Enumeration { /// @@ -32,8 +30,8 @@ public static IReadOnlySet GetAll() return typeof(T) .GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly) .Select(field => field.GetValue(null)) - .WhereInstanceOf() - .ToImmutableHashSet(); + .OfType() + .ToFrozenSet(); } /// @@ -42,7 +40,7 @@ public static IReadOnlySet GetAll() /// Returns all of the enumeration entries for the current type. public static IReadOnlySet<(int Value, string Name)> GetEntries() { - return GetAll().Select(entry => entry.ToEntry()).ToImmutableHashSet(); + return GetAll().Select(entry => entry.ToEntry()).ToFrozenSet(); } /// @@ -51,7 +49,7 @@ public static IReadOnlySet GetAll() /// Returns all of the enumeration names for the current type. public static IReadOnlySet GetNames() { - return GetAll().Select(entry => entry.Name).ToImmutableHashSet(); + return GetAll().Select(entry => entry.Name).ToFrozenSet(); } /// @@ -60,6 +58,6 @@ public static IReadOnlySet GetNames() /// Returns all of the enumeration values for the current type. public static IReadOnlySet GetValues() { - return GetAll().Select(entry => entry.Value).ToImmutableHashSet(); + return GetAll().Select(entry => entry.Value).ToFrozenSet(); } } diff --git a/OnixLabs.Core/Enumeration.To.cs b/OnixLabs.Core/Enumeration.To.cs index 3eed646..800f49d 100644 --- a/OnixLabs.Core/Enumeration.To.cs +++ b/OnixLabs.Core/Enumeration.To.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,7 +19,7 @@ namespace OnixLabs.Core; public abstract partial class Enumeration { /// - /// Returns a that represents the current object. + /// Returns a that represents the current object. /// /// Returns a tuple that represents the current object. public (int Value, string Name) ToEntry() @@ -28,9 +28,9 @@ public abstract partial class Enumeration } /// - /// Returns a that represents the current object. + /// Returns a that represents the current object. /// - /// Returns a that represents the current object. + /// Returns a that represents the current object. public override string ToString() { return Name; diff --git a/OnixLabs.Core/Enumeration.cs b/OnixLabs.Core/Enumeration.cs index 6bd552f..7d9f063 100644 --- a/OnixLabs.Core/Enumeration.cs +++ b/OnixLabs.Core/Enumeration.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,29 +17,20 @@ namespace OnixLabs.Core; /// -/// Represents the base class for implementing enumeration classes. +/// Represents the base class for implementing enumerations. /// +/// The value of the enumeration entry. +/// The name of the enumeration entry. /// The underlying enumeration type. -public abstract partial class Enumeration : IEquatable, IComparable, IComparable where T : Enumeration +public abstract partial class Enumeration(int value, string name) : IEquatable, IComparable, IComparable where T : Enumeration { - /// - /// Initializes a new instance of the class. - /// - /// The value of the enumeration entry. - /// The name of the enumeration entry. - protected Enumeration(int value, string name) - { - Value = value; - Name = name; - } - /// /// Gets the name of the enumeration entry. /// - public string Name { get; } + public string Name { get; } = name; /// /// Gets the value of the enumeration entry. /// - public int Value { get; } + public int Value { get; } = value; } diff --git a/OnixLabs.Core/Extensions.Array.cs b/OnixLabs.Core/Extensions.Array.cs index c78835d..643c00b 100644 --- a/OnixLabs.Core/Extensions.Array.cs +++ b/OnixLabs.Core/Extensions.Array.cs @@ -1,18 +1,17 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.ComponentModel; namespace OnixLabs.Core; @@ -24,46 +23,38 @@ namespace OnixLabs.Core; public static class ArrayExtensions { /// - /// Creates a copy of the current array. + /// Creates a copy of the current . /// - /// The array to copy. + /// The current to copy. /// The underlying type of the array. - /// Returns an exact copy of the current array. + /// Returns an exact copy of the current . public static T[] Copy(this T[] array) { - return Copy(array, 0, array.Length); + return [..array]; } /// - /// Creates a copy of the current array. + /// Creates a copy of the current . /// - /// The array to copy. + /// The current to copy. /// The index of the array to begin copying from. /// The number of elements of the array to copy. /// The underlying type of the array. - /// Returns an exact copy of the current array. + /// Returns an exact copy of the current . public static T[] Copy(this T[] array, int index, int count) { - T[] result = new T[count]; - Array.Copy(array, index, result, 0, count); - - return result; + return [..array[index..(index + count)]]; } /// - /// Concatenates the current array with another array. + /// Concatenates the current with another . /// - /// The source array to concatenate with the other array. - /// The other array to concatenate with the source array. - /// The underlying type of the array. - /// Returns the current array concatenated with the other array. + /// The source to concatenate with the other . + /// The other to concatenate with the source . + /// The underlying type of the . + /// Returns the current concatenated with the other . public static T[] ConcatenateWith(this T[] array, T[] other) { - T[] result = new T[array.Length + other.Length]; - - Array.Copy(array, 0, result, 0, array.Length); - Array.Copy(other, 0, result, array.Length, other.Length); - - return result; + return [..array, ..other]; } } diff --git a/OnixLabs.Core/Extensions.Object.cs b/OnixLabs.Core/Extensions.Object.cs index 49a30d2..8005057 100644 --- a/OnixLabs.Core/Extensions.Object.cs +++ b/OnixLabs.Core/Extensions.Object.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,6 +17,7 @@ using System.ComponentModel; using System.Linq; using System.Reflection; +using OnixLabs.Core.Reflection; namespace OnixLabs.Core; @@ -27,14 +28,14 @@ namespace OnixLabs.Core; public static class ObjectExtensions { /// - /// Provides a mechanism to compare the current to compare to the specified object. + /// Compares the current instance with the specified instance. /// - /// The current to compare to the specified object. - /// The to compare to the current . + /// The left-hand instance to compare. + /// The right-hand instance to compare. /// The underlying type of the current . /// Returns a signed integer that indicates the relative order of the objects being compared. - /// If the specified object is not null, or of the specified type. - public static int CompareObject(this IComparable comparable, object? obj) + /// If the specified object is not , or of the specified type. + public static int CompareToObject(this IComparable comparable, object? obj) { if (obj is null) return 1; if (obj is T other) return comparable.CompareTo(other); @@ -42,10 +43,10 @@ public static int CompareObject(this IComparable comparable, object? obj) } /// - /// Gets the representation of the current formatted as a record. + /// Gets a record-like representation of the current instance. /// - /// The to format as a record. - /// Returns the representation of the current formatted as a record. + /// The current instance. + /// Returns a record-like representation of the current instance. public static string ToRecordString(this object value) { Type type = value.GetType(); @@ -54,6 +55,6 @@ public static string ToRecordString(this object value) .GetProperties(BindingFlags.Public | BindingFlags.Instance) .Select(property => $"{property.Name} = {property.GetValue(value)}"); - return $"{type.Name} {{ {string.Join(", ", properties)} }}"; + return $"{type.GetName()} {{ {string.Join(", ", properties)} }}"; } } diff --git a/OnixLabs.Core/Extensions.String.cs b/OnixLabs.Core/Extensions.String.cs index 3c050c0..4a92b91 100644 --- a/OnixLabs.Core/Extensions.String.cs +++ b/OnixLabs.Core/Extensions.String.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,7 +13,6 @@ // limitations under the License. using System; -using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Linq; @@ -30,233 +29,293 @@ public static class StringExtensions /// /// The value of an index not found. /// - private const int IndexNotFound = -1; + private const int NotFound = -1; /// - /// Repeats the current by the specified number of repetitions. + /// The default string comparison. /// - /// The value to repeat. - /// The specified number of repetitions to repeat by. - /// Returns a new containing the repeated value. + private const StringComparison DefaultComparison = StringComparison.Ordinal; + + /// + /// The default date/time styles. + /// + private const DateTimeStyles DefaultStyles = DateTimeStyles.None; + + /// + /// The default encoding. + /// + private static readonly Encoding DefaultEncoding = Encoding.UTF8; + + /// + /// Repeats the current by the specified number of repetitions. + /// + /// The instance to repeat. + /// The number of repetitions of the current instance. + /// Returns a new instance representing the repetition of the current instance. public static string Repeat(this string value, int count) { - if (count <= 0) return string.Empty; - IEnumerable repetitions = Enumerable.Repeat(value, count); - return string.Join(string.Empty, repetitions); + return count > 0 ? string.Join(string.Empty, Enumerable.Repeat(value, count)) : string.Empty; } /// - /// Returns a substring before the first occurrence of the specified delimiter. + /// Obtains a sub-string before the specified index within the current instance. /// - /// The original from which to obtain a sub-string. - /// The delimiter to find within the original string. - /// The value to return if the delimiter is not found, which defaults to the original string. - /// Returns a substring before the first occurrence of the specified delimiter. - public static string SubstringBeforeFirst(this string value, char delimiter, string? defaultValue = null) + /// The current instance from which to obtain a sub-string. + /// The index in the current from which to obtain a sub-string. + /// + /// The value to return in the event that the index is less than zero. + /// If the default value is then the current instance is returned. + /// + /// + /// Returns a sub-string before the specified index. If the index is less than zero, then the default value will be returned. + /// If the default value is , then the current instance will be returned. + /// + private static string SubstringBeforeIndex(this string value, int index, string? defaultValue = null) { - int index = value.IndexOf(delimiter); - - return index switch - { - IndexNotFound => defaultValue ?? value, - _ => value[..index] - }; + return index <= NotFound ? defaultValue ?? value : value[..index]; } /// - /// Returns a substring before the first occurrence of the specified delimiter. + /// Obtains a sub-string after the specified index within the current instance. /// - /// The original from which to obtain a sub-string. - /// The delimiter to find within the original string. - /// The value to return if the delimiter is not found, which defaults to the original string. - /// Specifies the string comparison rule for the search. - /// Returns a substring before the first occurrence of the specified delimiter. - public static string SubstringBeforeFirst(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = StringComparison.Ordinal) + /// The current instance from which to obtain a sub-string. + /// The index in the current from which to obtain a sub-string. + /// The offset from the index which marks the beginning of the sub-string. + /// + /// The value to return in the event that the index is less than zero. + /// If the default value is then the current instance is returned. + /// + /// + /// Returns a sub-string after the specified index. If the index is less than zero, then the default value will be returned. + /// If the default value is , then the current instance will be returned. + /// + private static string SubstringAfterIndex(this string value, int index, int offset, string? defaultValue = null) { - int index = value.IndexOf(delimiter, comparison); - - return index switch - { - IndexNotFound => defaultValue ?? value, - _ => value[..index] - }; + return index <= NotFound ? defaultValue ?? value : value[(index + offset)..value.Length]; } /// - /// Returns a substring before the last occurrence of the specified delimiter. + /// Obtains a sub-string before the first occurrence of the specified delimiter within the current instance. /// - /// The original from which to obtain a sub-string. - /// The delimiter to find within the original string. - /// The value to return if the delimiter is not found, which defaults to the original string. - /// Returns a substring before the last occurrence of the specified delimiter. - public static string SubstringBeforeLast(this string value, char delimiter, string? defaultValue = null) + /// The current instance from which to obtain a sub-string. + /// The delimiter to find within the current instance. + /// + /// The value to return in the event that the delimiter is not found in the current instance. + /// If the default value is then the current instance is returned. + /// + /// + /// Returns a sub-string before the first occurrence of the specified delimiter within the current instance. + /// If the delimiter is not found, then the default value will be returned. + /// If the default value is , then the current instance is returned. + /// + public static string SubstringBeforeFirst(this string value, char delimiter, string? defaultValue = null) { - int index = value.LastIndexOf(delimiter); - - return index switch - { - IndexNotFound => defaultValue ?? value, - _ => value[..index] - }; + return value.SubstringBeforeIndex(value.IndexOf(delimiter), defaultValue); } /// - /// Returns a substring before the last occurrence of the specified delimiter. + /// Obtains a sub-string before the first occurrence of the specified delimiter within the current instance. /// - /// The original from which to obtain a sub-string. - /// The delimiter to find within the original string. - /// The value to return if the delimiter is not found, which defaults to the original string. - /// Specifies the string comparison rule for the search. - /// Returns a substring before the last occurrence of the specified delimiter. - public static string SubstringBeforeLast(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = StringComparison.Ordinal) + /// The current instance from which to obtain a sub-string. + /// The delimiter to find within the current instance. + /// + /// The value to return in the event that the delimiter is not found in the current instance. + /// If the default value is then the current instance is returned. + /// + /// + /// The culture, case and sort rules that will be applied when searching for the specified delimiter. + /// The default value is . + /// + /// + ///Returns a sub-string before the first occurrence of the specified delimiter within the current instance. + /// If the delimiter is not found, then the default value will be returned. + /// If the default value is , then the current instance is returned. + /// + public static string SubstringBeforeFirst(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = DefaultComparison) { - int index = value.LastIndexOf(delimiter, comparison); - - return index switch - { - IndexNotFound => defaultValue ?? value, - _ => value[..index] - }; + return value.SubstringBeforeIndex(value.IndexOf(delimiter, comparison), defaultValue); } /// - /// Returns a substring after the first occurrence of the specified delimiter. + /// Obtains a sub-string before the last occurrence of the specified delimiter within the current instance. /// - /// The original from which to obtain a sub-string. - /// The delimiter to find within the original string. - /// The value to return if the delimiter is not found, which defaults to the original string. - /// Returns a substring after the first occurrence of the specified delimiter. - public static string SubstringAfterFirst(this string value, char delimiter, string? defaultValue = null) + /// The current instance from which to obtain a sub-string. + /// The delimiter to find within the current instance. + /// + /// The value to return in the event that the delimiter is not found in the current instance. + /// If the default value is then the current instance is returned. + /// + /// + ///Returns a sub-string before the last occurrence of the specified delimiter within the current instance. + /// If the delimiter is not found, then the default value will be returned. + /// If the default value is , then the current instance is returned. + /// + public static string SubstringBeforeLast(this string value, char delimiter, string? defaultValue = null) { - int index = value.IndexOf(delimiter); - - return index switch - { - IndexNotFound => defaultValue ?? value, - _ => value[(index + 1)..value.Length] - }; + return value.SubstringBeforeIndex(value.LastIndexOf(delimiter), defaultValue); } /// - /// Returns a substring after the first occurrence of the specified delimiter. + /// Obtains a sub-string before the last occurrence of the specified delimiter within the current instance. /// - /// The original from which to obtain a sub-string. - /// The delimiter to find within the original string. - /// The value to return if the delimiter is not found, which defaults to the original string. - /// Specifies the string comparison rule for the search. - /// Returns a substring after the first occurrence of the specified delimiter. - public static string SubstringAfterFirst(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = StringComparison.Ordinal) + /// The current instance from which to obtain a sub-string. + /// The delimiter to find within the current instance. + /// + /// The value to return in the event that the delimiter is not found in the current instance. + /// If the default value is then the current instance is returned. + /// + /// + /// The culture, case and sort rules that will be applied when searching for the specified delimiter. + /// The default value is . + /// + /// + ///Returns a sub-string before the last occurrence of the specified delimiter within the current instance. + /// If the delimiter is not found, then the default value will be returned. + /// If the default value is , then the current instance is returned. + /// + public static string SubstringBeforeLast(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = DefaultComparison) { - int index = value.IndexOf(delimiter, comparison); - - return index switch - { - IndexNotFound => defaultValue ?? value, - _ => value[(index + delimiter.Length)..value.Length] - }; + return value.SubstringBeforeIndex(value.LastIndexOf(delimiter, comparison), defaultValue); } /// - /// Returns a substring after the last occurrence of the specified delimiter. + /// Obtains a sub-string after the first occurrence of the specified delimiter within the current instance. /// - /// The original from which to obtain a sub-string. - /// The delimiter to find within the original string. - /// The value to return if the delimiter is not found, which defaults to the original string. - /// Returns a substring after the last occurrence of the specified delimiter. - public static string SubstringAfterLast(this string value, char delimiter, string? defaultValue = null) + /// The current instance from which to obtain a sub-string. + /// The delimiter to find within the current instance. + /// + /// The value to return in the event that the delimiter is not found in the current instance. + /// If the default value is then the current instance is returned. + /// + /// + /// Returns a sub-string after the first occurrence of the specified delimiter within the current instance. + /// If the delimiter is not found, then the default value will be returned. + /// If the default value is , then the current instance is returned. + /// + public static string SubstringAfterFirst(this string value, char delimiter, string? defaultValue = null) { - int index = value.LastIndexOf(delimiter); - - return index switch - { - IndexNotFound => defaultValue ?? value, - _ => value[(index + 1)..value.Length] - }; + return value.SubstringAfterIndex(value.IndexOf(delimiter), 1, defaultValue); } /// - /// Returns a substring after the last occurrence of the specified delimiter. + /// Obtains a sub-string after the first occurrence of the specified delimiter within the current instance. /// - /// The original from which to obtain a sub-string. - /// The delimiter to find within the original string. - /// The value to return if the delimiter is not found, which defaults to the original string. - /// Specifies the string comparison rule for the search. - /// Returns a substring after the last occurrence of the specified delimiter. - public static string SubstringAfterLast(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = StringComparison.Ordinal) + /// The current instance from which to obtain a sub-string. + /// The delimiter to find within the current instance. + /// + /// The value to return in the event that the delimiter is not found in the current instance. + /// If the default value is then the current instance is returned. + /// + /// + /// The culture, case and sort rules that will be applied when searching for the specified delimiter. + /// The default value is . + /// + /// + ///Returns a sub-string after the first occurrence of the specified delimiter within the current instance. + /// If the delimiter is not found, then the default value will be returned. + /// If the default value is , then the current instance is returned. + /// + public static string SubstringAfterFirst(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = DefaultComparison) { - int index = value.LastIndexOf(delimiter, comparison); + return value.SubstringAfterIndex(value.IndexOf(delimiter, comparison), delimiter.Length, defaultValue); + } - return index switch - { - IndexNotFound => defaultValue ?? value, - _ => value[(index + delimiter.Length)..value.Length] - }; + /// + /// Obtains a sub-string after the last occurrence of the specified delimiter within the current instance. + /// + /// The current instance from which to obtain a sub-string. + /// The delimiter to find within the current instance. + /// + /// The value to return in the event that the delimiter is not found in the current instance. + /// If the default value is then the current instance is returned. + /// + /// + ///Returns a sub-string after the last occurrence of the specified delimiter within the current instance. + /// If the delimiter is not found, then the default value will be returned. + /// If the default value is , then the current instance is returned. + /// + public static string SubstringAfterLast(this string value, char delimiter, string? defaultValue = null) + { + return value.SubstringAfterIndex(value.LastIndexOf(delimiter), 1, defaultValue); } /// - /// Converts the current to a array using the default . + /// Obtains a sub-string after the last occurrence of the specified delimiter within the current instance. /// - /// The original from which to obtain a byte array. - /// Returns a array using the default . - public static byte[] ToByteArray(this string value) + /// The current instance from which to obtain a sub-string. + /// The delimiter to find within the current instance. + /// + /// The value to return in the event that the delimiter is not found in the current instance. + /// If the default value is then the current instance is returned. + /// + /// + /// The culture, case and sort rules that will be applied when searching for the specified delimiter. + /// The default value is . + /// + /// + ///Returns a sub-string after the last occurrence of the specified delimiter within the current instance. + /// If the delimiter is not found, then the default value will be returned. + /// If the default value is , then the current instance is returned. + /// + public static string SubstringAfterLast(this string value, string delimiter, string? defaultValue = null, StringComparison comparison = DefaultComparison) { - return ToByteArray(value, Encoding.Default); + return value.SubstringAfterIndex(value.LastIndexOf(delimiter, comparison), 1, defaultValue); } /// - /// Converts the current to a array using the specified . + /// Converts the current instance into a new instance. /// - /// The original from which to obtain a byte array. - /// The which will be used to convert the current to a array. - /// Returns a array using the specified . - public static byte[] ToByteArray(this string value, Encoding encoding) + /// The current from which to obtain a . + /// The encoding that will be used to convert the current into a . + /// Returns a new representation of the current instance. + public static byte[] ToByteArray(this string value, Encoding? encoding = null) { - return encoding.GetBytes(value); + return (encoding ?? DefaultEncoding).GetBytes(value); } /// - /// Converts the current to a . + /// Converts the current instance into a new instance. /// - /// The original from which to obtain a . - /// An object that supplies culture-specific formatting information. - /// A bitwise combination of the enumeration values that indicates the style elements that can be present. - /// Returns a parsed from the current value. - public static DateTime ToDateTime(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DateTimeStyles.None) + /// The current instance to convert. + /// An object that provides culture-specific formatting information. + /// A bit-wise combination of enumeration values that indicate the style elements that can be present. + /// Returns a new instance parsed from the current instance. + public static DateTime ToDateTime(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DefaultStyles) { return DateTime.Parse(value, provider, styles); } /// - /// Converts the current to a . + /// Converts the current instance into a new instance. /// - /// The original from which to obtain a . - /// An object that supplies culture-specific formatting information. - /// A bitwise combination of the enumeration values that indicates the style elements that can be present. - /// Returns a parsed from the current value. - public static DateOnly ToDateOnly(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DateTimeStyles.None) + /// The current instance to convert. + /// An object that provides culture-specific formatting information. + /// A bit-wise combination of enumeration values that indicate the style elements that can be present. + /// Returns a new instance parsed from the current instance. + public static DateOnly ToDateOnly(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DefaultStyles) { return DateOnly.Parse(value, provider, styles); } /// - /// Converts the current to a . + /// Converts the current instance into a new instance. /// - /// The original from which to obtain a . - /// An object that supplies culture-specific formatting information. - /// A bitwise combination of the enumeration values that indicates the style elements that can be present. - /// Returns a parsed from the current value. - public static TimeOnly ToTimeOnly(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DateTimeStyles.None) + /// The current instance to convert. + /// An object that provides culture-specific formatting information. + /// A bit-wise combination of enumeration values that indicate the style elements that can be present. + /// Returns a new instance parsed from the current instance. + public static TimeOnly ToTimeOnly(this string value, IFormatProvider? provider = null, DateTimeStyles styles = DefaultStyles) { return TimeOnly.Parse(value, provider, styles); } /// - /// Copies the contents of the current into the destination . + /// Tries to copy the current instance into the destination . /// - /// The current value to copy. - /// The into which to copy the current contents. + /// The current instance to copy. + /// The into which the current contents will be copied. /// The number of characters written to the destination . - /// Returns if the data was copied into the destination span; otherwise, if the destination was too short. + /// Returns if the current instance was copied into the destination ; otherwise, if the destination was too short. public static bool TryCopyTo(this string value, Span destination, out int charsWritten) { bool result = value.TryCopyTo(destination); @@ -265,24 +324,24 @@ public static bool TryCopyTo(this string value, Span destination, out int } /// - /// Converts the current between the specified before and after values. + /// Wraps the current instance between the specified before and after instances. /// - /// The current value to wrap. - /// The that should precede the current value. - /// The that should succeed the current value. - /// Returns the current wrapped between the specified before and after values. + /// The current instance to wrap. + /// The that should precede the current instance. + /// The that should succeed the current instance. + /// Returns a new instance representing the current instance, wrapped between the specified before and after instances. public static string Wrap(this string value, char before, char after) { return $"{before}{value}{after}"; } /// - /// Converts the current between the specified before and after values. + /// Wraps the current instance between the specified before and after instances. /// - /// The current value to wrap. - /// The that should precede the current value. - /// The that should succeed the current value. - /// Returns the current wrapped between the specified before and after values. + /// The current instance to wrap. + /// The that should precede the current instance. + /// The that should succeed the current instance. + /// Returns a new instance representing the current instance, wrapped between the specified before and after instances. public static string Wrap(this string value, string before, string after) { return $"{before}{value}{after}"; diff --git a/OnixLabs.Core/Text/Base16.Constants.cs b/OnixLabs.Core/IBinaryConvertible.cs similarity index 55% rename from OnixLabs.Core/Text/Base16.Constants.cs rename to OnixLabs.Core/IBinaryConvertible.cs index 268622f..a6bace1 100644 --- a/OnixLabs.Core/Text/Base16.Constants.cs +++ b/OnixLabs.Core/IBinaryConvertible.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,17 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -namespace OnixLabs.Core.Text; +namespace OnixLabs.Core; -public readonly partial struct Base16 +/// +/// Defines a type that is convertible to a binary representation. +/// +public interface IBinaryConvertible { /// - /// Gets an empty value. + /// Gets the underlying representation of the current instance. /// - public static Base16 Empty => new([]); - - /// - /// Gets the default Base-16 format. - /// - private const char DefaultFormat = 'L'; + /// Return the underlying representation of the current instance. + byte[] ToByteArray(); } diff --git a/OnixLabs.Core/IValueComparable.cs b/OnixLabs.Core/IValueComparable.cs new file mode 100644 index 0000000..921fdeb --- /dev/null +++ b/OnixLabs.Core/IValueComparable.cs @@ -0,0 +1,73 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core; + +/// +/// Defines an extension to the default and interfaces, +/// including equality, inequality, greater than, greater than or equal, less than, and less than or equal operators. +/// +/// The underlying type of the objects to compare. +public interface IValueComparable : IComparable, IComparable where T : IValueComparable +{ + /// + /// Performs an equality comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . + public static abstract bool operator ==(T left, T right); + + /// + /// Performs an inequality comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . + public static abstract bool operator !=(T left, T right); + + /// + /// Performs a greater than comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is greater than the right-hand instance; otherwise, . + public static abstract bool operator >(T left, T right); + + /// + /// Performs a greater than or equal comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is greater than or equal to the right-hand instance; otherwise, . + public static abstract bool operator >=(T left, T right); + + /// + /// Performs a less than comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is less than the right-hand instance; otherwise, . + public static abstract bool operator <(T left, T right); + + /// + /// Performs a less than or equal comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is less than or equal to the right-hand instance; otherwise, . + public static abstract bool operator <=(T left, T right); +} diff --git a/OnixLabs.Core/IValueEquatable.cs b/OnixLabs.Core/IValueEquatable.cs new file mode 100644 index 0000000..eafb819 --- /dev/null +++ b/OnixLabs.Core/IValueEquatable.cs @@ -0,0 +1,40 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core; + +/// +/// Defines an extension to the default interface, including equality and inequality operators. +/// +/// The underlying type of the objects to compare. +public interface IValueEquatable : IEquatable where T : IValueEquatable +{ + /// + /// Performs an equality comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . + public static abstract bool operator ==(T left, T right); + + /// + /// Performs an inequality comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . + public static abstract bool operator !=(T left, T right); +} diff --git a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs index 6954ee2..41b7ace 100644 --- a/OnixLabs.Core/Linq/Extensions.IEnumerable.cs +++ b/OnixLabs.Core/Linq/Extensions.IEnumerable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -30,39 +30,36 @@ public static class IEnumerableExtensions /// /// Determines whether all elements of the current are equal by a specified property. /// - /// The on which to perform the operation. - /// The selector function which will be used to select each property from each element. + /// The current on which to perform the operation. + /// The selector function which will be used to select the desired property from each element. /// The underlying type of the . /// The underlying type of each selected element. /// Returns if all selected element properties are equal; otherwise . public static bool AllEqualBy(this IEnumerable enumerable, Func selector) { - ISet elements = enumerable.Select(selector).ToHashSet(); - return elements.IsNotEmpty() && elements.IsSingle(); + return enumerable.Select(selector).Distinct().IsSingle(); } /// /// Determines whether any elements of the current are equal by a specified property. /// - /// The on which to perform the operation. - /// The selector function which will be used to select each property from each element. + /// The current on which to perform the operation. + /// The selector function which will be used to select the desired property from each element. /// The underlying type of the . /// The underlying type of each selected element. /// Returns if any selected element properties are equal; otherwise . public static bool AnyEqualBy(this IEnumerable enumerable, Func selector) { - IList elements = enumerable.Select(selector).ToList(); - ISet distinctElements = elements.ToHashSet(); - return distinctElements.IsNotEmpty() && distinctElements.Count < elements.Count; + return enumerable.GroupBy(selector).Any(group => group.Count() > 1); } /// - /// Obtains a number that represents how many elements in the the current do not satisfy the specified predicate condition. + /// Obtains a number that represents how many elements in the current do not satisfy the specified predicate condition. /// - /// The on which to perform the operation. + /// The current on which to perform the operation. /// The function to test each element for a condition. /// The underlying type of the . - /// Returns a number that represents how many elements in the the current do not satisfy the specified predicate condition. + /// Returns a number that represents how many elements in the current do not satisfy the specified predicate condition. public static int CountNot(this IEnumerable enumerable, Func predicate) { return enumerable.Count(element => !predicate(element)); @@ -71,7 +68,7 @@ public static int CountNot(this IEnumerable enumerable, Func pred /// /// Performs the specified for each element of the current . /// - /// The over which to iterate. + /// The current over which to iterate. /// The to perform for each element. /// The underlying type of the . public static void ForEach(this IEnumerable enumerable, Action action) @@ -82,21 +79,21 @@ public static void ForEach(this IEnumerable enumerable, Action action) /// /// Gets the content hash code of the elements of the current . /// - /// The from which to compute a content hash code. + /// The current from which to compute a content hash code. /// The underlying type of the . /// Returns the computed content hash code of the current . public static int GetContentHashCode(this IEnumerable enumerable) { - HashCode hashCode = new(); - enumerable.ForEach(item => hashCode.Add(item)); - return hashCode.ToHashCode(); + HashCode result = new(); + enumerable.ForEach(element => result.Add(element)); + return result.ToHashCode(); } /// /// Determines whether the current is empty. /// - /// The on which to perform the operation. - /// he underlying type of the . + /// The current on which to perform the operation. + /// The underlying type of the . /// Returns if the is empty; otherwise, . public static bool IsEmpty(this IEnumerable enumerable) { @@ -106,18 +103,18 @@ public static bool IsEmpty(this IEnumerable enumerable) /// /// Determines whether the current is not empty. /// - /// The on which to perform the operation. + /// The current on which to perform the operation. /// The underlying type of the . /// Returns if the is not empty; otherwise, . public static bool IsNotEmpty(this IEnumerable enumerable) { - return !enumerable.IsEmpty(); + return enumerable.Any(); } /// /// Determines whether the current contains a single element. /// - /// The on which to perform the operation. + /// The current on which to perform the operation. /// The underlying type of the . /// Returns if the contains a single element; otherwise, . public static bool IsSingle(this IEnumerable enumerable) @@ -128,44 +125,35 @@ public static bool IsSingle(this IEnumerable enumerable) /// /// Determines whether the current contains an even number of elements. /// - /// The on which to perform the operation. + /// The current on which to perform the operation. + /// The function to test each element for a condition. /// The underlying type of the . /// Returns if the contains an even number of elements; otherwise, . - public static bool IsCountEven(this IEnumerable enumerable) + public static bool IsCountEven(this IEnumerable enumerable, Func? predicate = null) { - return enumerable.LongCount() % 2 == 0; + return enumerable.LongCount(element => predicate?.Invoke(element) ?? true) % 2 == 0; } /// /// Determines whether the current contains an odd number of elements. /// - /// The on which to perform the operation. + /// The current on which to perform the operation. + /// The function to test each element for a condition. /// The underlying type of the . /// Returns if the contains an odd number of elements; otherwise, . - public static bool IsCountOdd(this IEnumerable enumerable) - { - return !enumerable.IsCountEven(); - } - - /// - /// Joins the elements of the current into a . - /// - /// The to join. - /// The underlying type of the . - /// Returns the elements of the current , joined into a string. - public static string JoinToString(this IEnumerable enumerable) + public static bool IsCountOdd(this IEnumerable enumerable, Func? predicate = null) { - return enumerable.JoinToString(", "); + return enumerable.LongCount(element => predicate?.Invoke(element) ?? true) % 2 != 0; } /// - /// Joins the elements of the current into a . + /// Joins the elements of the current into a instance. /// - /// The to join. + /// The current to join. /// The separator which will appear between joined elements. /// The underlying type of the . - /// Returns the elements of the current , joined into a string. - public static string JoinToString(this IEnumerable enumerable, string separator) + /// Returns the elements of the current , joined into a instance. + public static string JoinToString(this IEnumerable enumerable, string separator = ", ") { return string.Join(separator, enumerable); } @@ -173,7 +161,7 @@ public static string JoinToString(this IEnumerable enumerable, string sepa /// /// Determines whether none of the elements of the current satisfy the specified predicate condition. /// - /// The on which to perform the operation. + /// The current on which to perform the operation. /// The function to test each element for a condition. /// The underlying type of the . /// Returns if none of the elements of the current satisfy the specified predicate condition; otherwise, . @@ -185,46 +173,32 @@ public static bool None(this IEnumerable enumerable, Func predica /// /// Calculates the sum of the elements of the current . /// - /// The to sum. - /// The underlying type of the . + /// The current to sum. + /// The underlying type of the . /// Returns the sum of the elements of the current . - public static T Sum(this IEnumerable enumerable) where T : INumber + public static T Sum(this IEnumerable enumerable) where T : INumberBase { - IEnumerable elements = enumerable.ToArray(); - return elements.IsEmpty() ? T.Zero : elements.Aggregate((left, right) => left + right); + IEnumerable numbers = enumerable as T[] ?? enumerable.ToArray(); + return numbers.IsEmpty() ? T.Zero : numbers.Aggregate((left, right) => left + right); } /// /// Calculates the sum of the elements of the current . /// - /// The to sum. - /// The selector function which will be used to select each property from each element. + /// The current to sum. + /// The selector function which will be used to select each property from each element. /// The underlying type of the . - /// The underlying type of each element to sum. + /// The underlying type of each element to sum. /// Returns the sum of the elements of the current . - public static TResult SumBy(this IEnumerable enumerable, Func selector) where TResult : INumber + public static TResult SumBy(this IEnumerable enumerable, Func selector) where TResult : INumberBase { return enumerable.Select(selector).Sum(); } - /// - /// Filters the current to only elements of the specified type. - /// - /// The on which to perform the operation. - /// The underlying type of the . - /// Returns a new containing only elements of the specified type. - public static IEnumerable WhereInstanceOf(this IEnumerable enumerable) - { - foreach (object? element in enumerable) - { - if (element is T elementOfType) yield return elementOfType; - } - } - /// /// Filters the current elements that do not satisfy the specified predicate condition. /// - /// The on which to perform the operation. + /// The current on which to perform the operation. /// The function to test each element for a condition. /// The underlying type of the . /// Returns a new that contains elements that do not satisfy the condition. @@ -234,12 +208,12 @@ public static IEnumerable WhereNot(this IEnumerable enumerable, Func - /// Filters the current elements that are not null. + /// Filters the current elements that are not . /// - /// The on which to perform the operation. + /// The current on which to perform the operation. /// The underlying type of the . - /// Returns a new that contains elements that are not null. - public static IEnumerable WhereNotNull(this IEnumerable enumerable) + /// Returns a new that contains elements that are not . + public static IEnumerable WhereNotNull(this IEnumerable enumerable) where T : notnull { return enumerable.Where(element => element is not null)!; } @@ -247,24 +221,24 @@ public static IEnumerable WhereNotNull(this IEnumerable enumerable) /// /// Formats the current as a collection string. /// - /// The to format. + /// The current to format. /// The underlying type of the . - /// Returns a collection representation of the current . + /// Returns a new instance representing the current . public static string ToCollectionString(this IEnumerable enumerable) { - return string.Join(", ", enumerable).Wrap('[', ']'); + return enumerable.JoinToString().Wrap('[', ']'); } /// - /// Formats each element of the current current as a collection string. + /// Formats the current as a collection string. /// - /// The to format. + /// The current to format. /// The format which will be applied to each element. - /// The provider to use to format the value. + /// An object that provides culture-specific formatting information. /// The underlying type of the . - /// Returns a collection representation of the current . - public static string ToCollectionString(this IEnumerable enumerable, string format, IFormatProvider? formatProvider = null) where T : IFormattable + /// Returns a new instance representing the current . + public static string ToCollectionString(this IEnumerable enumerable, string format, IFormatProvider? provider = null) where T : IFormattable { - return enumerable.Select(element => element.ToString(format, formatProvider)).ToCollectionString(); + return enumerable.Select(element => element.ToString(format, provider)).ToCollectionString(); } } diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj index 6c4ab47..95be286 100644 --- a/OnixLabs.Core/OnixLabs.Core.csproj +++ b/OnixLabs.Core/OnixLabs.Core.csproj @@ -9,7 +9,7 @@ ONIXLabs Core API for .NET 6.0.0 en - Copyright © ONIXLabs 2020-2023 + Copyright © ONIXLabs 2020 https://github.com/onix-labs/onixlabs-dotnet 6.0.0 @@ -41,6 +41,5 @@ - diff --git a/OnixLabs.Core/Preconditions.cs b/OnixLabs.Core/Preconditions.cs index 313c6a3..e149ef1 100644 --- a/OnixLabs.Core/Preconditions.cs +++ b/OnixLabs.Core/Preconditions.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,69 +18,78 @@ namespace OnixLabs.Core; /// -/// Provides methods for performing pre-conditions and guard clauses. +/// Provides general methods for performing pre-conditions and guard clauses. /// public static class Preconditions { /// - /// Performs a general pre-condition check, which fails if the condition returns . + /// Performs a general pre-condition check that fails when the specified condition is . /// /// The condition to check. - /// The exception message to throw in the event that the condition fails. - /// If the condition fails. - public static void Check(bool condition, string message = "Check requirement failed.") + /// The exception message to throw in the event that the specified condition is . + /// If the specified condition is . + public static void Check(bool condition, string message = "Check failed.") { if (!condition) throw new InvalidOperationException(message); } /// - /// Performs a general pre-condition requirement that the specified value is not null, which fails if the value is null. + /// Performs a general pre-condition check that fails if the specified value is . /// /// The nullable value to check. - /// The exception message to throw in the event that the condition fails. + /// The exception message to throw in the event that the specified value is . /// The underlying type of the value. - /// Returns the specified value as non-nullable in the event that the value is not null. - /// If the condition fails because the value is null. + /// Returns a non-null value of the specified type. + /// If the specified value is . public static T CheckNotNull(T? value, string message = "Argument must not be null.") where T : notnull { return value ?? throw new InvalidOperationException(message); } /// - /// Performs a general pre-condition requirement, which fails if the condition returns . + /// Performs a general pre-condition requirement that fails when the specified condition is . /// - /// The condition of the requirement. - /// The exception message to throw in the event that the condition fails. - /// The name of the parameter which is invalid. - /// If the condition fails. + /// The condition to check. + /// The exception message to throw in the event that the specified condition is . + /// The name of the invalid paramter. + /// If the specified condition is . public static void Require(bool condition, string message = "Argument requirement failed.", string? parameterName = null) { if (!condition) throw new ArgumentException(message, parameterName); } /// - /// Performs a general pre-condition requirement that the specified value is not null, which fails if the value is null. + /// Performs a general pre-condition requirement that fails when the specified condition is . + /// + /// The condition to check. + /// The exception message to throw in the event that the specified condition is . + /// The name of the invalid paramter. + /// If the specified condition is . + public static void RequireWithinRange(bool condition, string message = "Argument is out of range.", string? parameterName = null) + { + if (!condition) throw new ArgumentOutOfRangeException(parameterName, message); + } + + /// + /// Performs a general pre-condition requirement that fails if the specified value is . /// /// The nullable value to check. - /// The exception message to throw in the event that the condition fails. - /// The name of the parameter which is invalid. + /// The exception message to throw in the event that the specified value is . + /// The name of the invalid parameter. /// The underlying type of the value. - /// Returns the specified value as non-nullable in the event that the value is not null. - /// If the condition fails because the value is null. - public static T RequireNotNull(T? value, string message = "Argument must not be null.", string? parameterName = null) - where T : notnull + /// Returns a non-null value of the specified type. + /// If the specified value is . + public static T RequireNotNull(T? value, string message = "Argument must not be null.", string? parameterName = null) where T : notnull { return value ?? throw new ArgumentNullException(parameterName, message); } /// - /// Performs a pre-condition requirement that the specified enum value is defined in the enum. + /// Performs a general pre-condition requirement that the specified value is defined by the specified type. /// /// The enum value to check. - /// The name of the parameter being checked. - /// The underlying type of the enum value. - /// Returns the specified enum value if it is defined in the enum. - /// If the specified value does not exist in the enum. + /// The name of the invalid parameter. + /// The underlying type of the . public static void RequireIsDefined(T value, string? parameterName = null) where T : struct, Enum { if (Enum.IsDefined(value)) return; diff --git a/OnixLabs.Core/Reflection/Extensions.Type.cs b/OnixLabs.Core/Reflection/Extensions.Type.cs index 45cb1d1..7ca3965 100644 --- a/OnixLabs.Core/Reflection/Extensions.Type.cs +++ b/OnixLabs.Core/Reflection/Extensions.Type.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -13,9 +13,7 @@ // limitations under the License. using System; -using System.Collections.Generic; using System.ComponentModel; -using System.Linq; namespace OnixLabs.Core.Reflection; @@ -31,31 +29,12 @@ public static class TypeExtensions private const char GenericTypeIdentifierMarker = '`'; /// - /// Gets the simple type name from the specified type, excluding any generic type parameters. + /// Gets the simple type name from the current instance. /// - /// The from which to obtain a simple type name. - /// Returns the simple type name from the specified type, excluding any generic type parameters. - public static string GetSimpleName(this Type type) + /// The current instance from which to obtain the simple name. + /// Returns the simple type name from the current instance. + public static string GetName(this Type type) { return type.Name.SubstringBeforeFirst(GenericTypeIdentifierMarker); } - - /// - /// Gets the formatted type name from the specified type, including any generic type parameters. - /// - /// The from which to obtain a formatted type name. - /// Returns the formatted type name from the specified type, including any generic type parameters. - public static string GetFormattedName(this Type type) - { - if (!type.Name.Contains(GenericTypeIdentifierMarker)) - { - return type.Name; - } - - IEnumerable genericTypeArguments = type.GenericTypeArguments.Select(GetFormattedName); - string typeName = type.Name.SubstringBeforeFirst(GenericTypeIdentifierMarker); - string generics = string.Join(", ", genericTypeArguments).Wrap("<", ">"); - - return typeName + generics; - } } diff --git a/OnixLabs.Core/Text/Base16.Create.cs b/OnixLabs.Core/Text/Base16.Create.cs deleted file mode 100644 index 0675c39..0000000 --- a/OnixLabs.Core/Text/Base16.Create.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base16 -{ - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base16 Create(byte[] value) - { - return new Base16(value); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base16 Create(ReadOnlySpan value) - { - return Create(value.ToArray()); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base16 Create(string value) - { - return Create(value.ToCharArray(), Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base16 Create(string value, Encoding encoding) - { - return Create(value.ToCharArray(), encoding); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base16 Create(char[] value) - { - return Create(value, Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base16 Create(char[] value, Encoding encoding) - { - return Create(encoding.GetBytes(value)); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base16 Create(ReadOnlySpan value) - { - return Create(value.ToArray(), Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base16 Create(ReadOnlySpan value, Encoding encoding) - { - return Create(value.ToArray(), encoding); - } -} diff --git a/OnixLabs.Core/Text/Base16.Equatable.cs b/OnixLabs.Core/Text/Base16.Equatable.cs index 7455877..dee52b2 100644 --- a/OnixLabs.Core/Text/Base16.Equatable.cs +++ b/OnixLabs.Core/Text/Base16.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Linq; using OnixLabs.Core.Linq; @@ -21,13 +20,13 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base16 { /// - /// Checks for equality between the current instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// Returns if the object is equal to the current instance; otherwise, . + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . public bool Equals(Base16 other) { - return value.SequenceEqual(other.value); + return other.value.SequenceEqual(value); } /// @@ -46,26 +45,26 @@ public override bool Equals(object? obj) /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(value.GetContentHashCode()); + return value.GetContentHashCode(); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(Base16 left, Base16 right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(Base16 left, Base16 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base16.Format.cs b/OnixLabs.Core/Text/Base16.Format.cs index c219429..ff7eb9f 100644 --- a/OnixLabs.Core/Text/Base16.Format.cs +++ b/OnixLabs.Core/Text/Base16.Format.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base16.Parse.cs b/OnixLabs.Core/Text/Base16.Parse.cs index 0e47928..880eae8 100644 --- a/OnixLabs.Core/Text/Base16.Parse.cs +++ b/OnixLabs.Core/Text/Base16.Parse.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,77 +19,62 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base16 { /// - /// Parses a Base-16 (Hexadecimal) value into a value. + /// Parses the specified Base-16 encoded value into a value. /// - /// The Base-16 (Hexadecimal) value to parse. - /// - /// An object that provides format-specific information about the specified value. - /// The parameter is ignored by the current implementation of . - /// - /// Returns a new instance. + /// The Base-16 encoded value to parse. + /// The format provider that will be used to decode the specified value. + /// Returns a new instance, parsed from the specified Base-16 encoded value. public static Base16 Parse(string value, IFormatProvider? provider = null) { return Parse(value.AsSpan(), provider); } /// - /// Parses a Base-16 (Hexadecimal) value into a value. + /// Parses the specified Base-16 encoded value into a value. /// - /// The Base-16 (Hexadecimal) value to parse. - /// - /// An object that provides format-specific information about the specified value. - /// The parameter is ignored by the current implementation of . - /// - /// Returns a new instance. + /// The Base-16 encoded value to parse. + /// The format provider that will be used to decode the specified value. + /// Returns a new instance, parsed from the specified Base-16 encoded value. public static Base16 Parse(ReadOnlySpan value, IFormatProvider? provider = null) { - if (TryParse(value, provider, out Base16 result)) return result; - throw new FormatException($"The input string '{value}' was not in a correct format."); + byte[] bytes = IBaseCodec.Base16.Decode(value, provider); + return new Base16(bytes); } /// - /// Tries to parse the specified Base-16 (Hexadecimal) value into a value. + /// Tries to parse the specified Base-16 encoded value into a value. /// - /// The Base-16 (Hexadecimal) value to parse. - /// - /// An object that provides format-specific information about the specified value. - /// The parameter is ignored by the current implementation of . - /// + /// The Base-16 encoded value to parse. + /// The format provider that will be used to decode the specified value. /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. + /// A new instance, parsed from the specified Base-16 encoded value, + /// or the default value if the specified Base-16 encoded could not be parsed. /// - /// Returns if the specified value was parsed successfully; otherwise, . + /// Returns if the specified Base-16 value was decoded successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out Base16 result) { return TryParse(value.AsSpan(), provider, out result); } /// - /// Tries to parse the specified Base-16 (Hexadecimal) value into a value. + /// Tries to parse the specified Base-16 encoded value into a value. /// - /// The Base-16 (Hexadecimal) value to parse. - /// - /// An object that provides format-specific information about the specified value. - /// The parameter is ignored by the current implementation of . - /// + /// The Base-16 encoded value to parse. + /// The format provider that will be used to decode the specified value. /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. + /// A new instance, parsed from the specified Base-16 encoded value, + /// or the default value if the specified Base-16 encoded could not be parsed. /// - /// Returns if the specified value was parsed successfully; otherwise, . + /// Returns if the specified Base-16 value was decoded successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base16 result) { - try + if (IBaseCodec.Base16.TryDecode(value, provider, out byte[] bytes)) { - byte[] bytes = Convert.FromHexString(value); - result = Create(bytes); + result = new Base16(bytes); return true; } - catch - { - result = Empty; - return false; - } + + result = default; + return false; } } diff --git a/OnixLabs.Core/Text/Base16.To.cs b/OnixLabs.Core/Text/Base16.To.cs index e24db9d..1cc48cd 100644 --- a/OnixLabs.Core/Text/Base16.To.cs +++ b/OnixLabs.Core/Text/Base16.To.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,56 +13,46 @@ // limitations under the License. using System; -using System.Text; namespace OnixLabs.Core.Text; public readonly partial struct Base16 { /// - /// Returns a array that represents the current object. + /// Gets the underlying representation of the current instance. /// - /// Returns a array that represents the current object. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { return value.Copy(); } /// - /// Gets the plain-text representation of the current value, using the default . + /// Returns a that represents the current object. /// - /// Returns the plain-text representation of the current value, using the default . - public string ToPlainTextString() - { - return ToPlainTextString(Encoding.Default); - } - - /// - /// Gets the plain-text representation of the current value. - /// - /// The which will be used to obtain a from the current value. - /// Returns the plain-text representation of the current value. - public string ToPlainTextString(Encoding encoding) + /// Returns a that represents the current object. + public override string ToString() { - return encoding.GetString(value); + return ToString(Base16FormatProvider.Invariant); } /// - /// Returns a that represents the current object. + /// Formats the value of the current instance using the specified format. /// - /// Returns a that represents the current object. - public override string ToString() + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(IFormatProvider? formatProvider) { - return ToString([DefaultFormat]); + return ToString(null, formatProvider); } /// /// Formats the value of the current instance using the specified format. /// - /// The format to use, or null to use the default format. + /// The format to use. /// The provider to use to format the value. /// The value of the current instance in the specified format. - public string ToString(string? format, IFormatProvider? formatProvider = null) + public string ToString(string? format, IFormatProvider? formatProvider) { return ToString(format.AsSpan(), formatProvider); } @@ -70,13 +60,11 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) /// /// Formats the value of the current instance using the specified format. /// - /// The format to use, or null to use the default format. + /// The format to use. /// The provider to use to format the value. /// The value of the current instance in the specified format. - public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider) { - char specifier = char.ToUpperInvariant(format.IsEmpty || format.IsWhiteSpace() ? DefaultFormat : format[0]); - string result = Convert.ToHexString(value); - return specifier == DefaultFormat ? result.ToLower() : result; + return IBaseCodec.Base16.Encode(value, formatProvider); } } diff --git a/OnixLabs.Core/Text/Base16.cs b/OnixLabs.Core/Text/Base16.cs index 5ec68c2..eeba0e6 100644 --- a/OnixLabs.Core/Text/Base16.cs +++ b/OnixLabs.Core/Text/Base16.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,24 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; + namespace OnixLabs.Core.Text; /// -/// Represents a Base-16 (hexadecimal) value. +/// Represents a Base-16 value. /// -public readonly partial struct Base16 : IBaseRepresentation +/// The underlying value. +public readonly partial struct Base16(ReadOnlySpan value) : IBaseValue { - /// - /// The underlying value. - /// - private readonly byte[] value; + private readonly byte[] value = value.ToArray(); /// - /// Initializes a new instance of the struct. + /// Initializes a new default value. /// - /// The underlying value. - private Base16(byte[] value) + public Base16() : this([]) { - this.value = value.Copy(); } } diff --git a/OnixLabs.Core/Text/Base16Codec.cs b/OnixLabs.Core/Text/Base16Codec.cs new file mode 100644 index 0000000..fcc49b4 --- /dev/null +++ b/OnixLabs.Core/Text/Base16Codec.cs @@ -0,0 +1,143 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Buffers; + +namespace OnixLabs.Core.Text; + +/// +/// Represents a codec for encoding and decoding Base-16 values. +/// +public sealed class Base16Codec : IBaseCodec +{ + private static readonly SearchValues Base16UppercaseValues = SearchValues.Create("ABCDEF"); + + private static readonly SearchValues Base16LowercaseValues = SearchValues.Create("abcdef"); + + /// + /// Encodes the specified value into a Base-16 representation. + /// + /// The value to encode into a Base-16 representation. + /// The format provider that will be used to encode the specified value. + /// Returns a new Base-16 representation encoded from the specified value. + public string Encode(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryEncode(value, provider, out string result)) return result; + throw new FormatException(IBaseCodec.EncodingFormatException); + } + + /// + /// Decodes the specified Base-16 representation into a . + /// + /// The Base-16 value to decode into a . + /// The format provider that will be used to decode the specified value. + /// Returns a new decoded from the specified value. + public byte[] Decode(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryDecode(value, provider, out byte[] result)) return result; + throw new FormatException(IBaseCodec.DecodingFormatException); + } + + /// + /// Tries to encode the specified value into a Base-16 representation. + /// + /// The value to encode into a Base-16 representation. + /// The format provider that will be used to encode the specified value. + /// + /// A new Base-16 representation encoded from the specified value, + /// or an empty string if the specified value could not be encoded. + /// + /// Returns if the specified value was encoded successfully; otherwise, . + public bool TryEncode(ReadOnlySpan value, IFormatProvider? provider, out string result) + { + try + { + if (value.IsEmpty) + { + result = string.Empty; + return true; + } + + if (provider is not null && provider is not Base16FormatProvider) + { + result = string.Empty; + return false; + } + + Base16FormatProvider formatProvider = provider as Base16FormatProvider ?? Base16FormatProvider.Invariant; + + result = formatProvider == Base16FormatProvider.Uppercase + ? Convert.ToHexString(value) + : Convert.ToHexString(value).ToLower(); + + return true; + } + catch + { + result = string.Empty; + return false; + } + } + + /// + /// Tries to decode the specified Base-16 representation into a . + /// + /// The Base-16 value to decode into a . + /// The format provider that will be used to decode the specified value. + /// + /// A new decoded from the specified value, + /// or an empty if the specified value could not be decoded. + /// + /// Returns if the specified value was decoded successfully; otherwise, . + public bool TryDecode(ReadOnlySpan value, IFormatProvider? provider, out byte[] result) + { + try + { + if (value.IsEmpty) + { + result = []; + return true; + } + + if (provider is not null && provider is not Base16FormatProvider) + { + result = []; + return false; + } + + Base16FormatProvider formatProvider = provider as Base16FormatProvider ?? Base16FormatProvider.Invariant; + + if (formatProvider == Base16FormatProvider.Uppercase && value.ContainsAny(Base16LowercaseValues)) + { + result = []; + return false; + } + + if (formatProvider == Base16FormatProvider.Lowercase && value.ContainsAny(Base16UppercaseValues)) + { + result = []; + return false; + } + + result = Convert.FromHexString(value); + return true; + } + catch + { + result = []; + return false; + } + } +} diff --git a/OnixLabs.Core/Text/Base16FormatProvider.cs b/OnixLabs.Core/Text/Base16FormatProvider.cs new file mode 100644 index 0000000..82541cf --- /dev/null +++ b/OnixLabs.Core/Text/Base16FormatProvider.cs @@ -0,0 +1,67 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +/// +/// Represents a Base-16 format provider. +/// +public sealed class Base16FormatProvider : Enumeration, IFormatProvider +{ + /// + /// Gets the invariant Base-16 format provider. + /// The invariant format provider favours lowercase for Base-16 encoding. + /// The alphabet provided by this format provider is not a strict Base-16 alphabet as it contains all uppercase and lowercase values. + /// + public static readonly Base16FormatProvider Invariant = new(0, nameof(Invariant), "0123456789ABCDEFabcdef"); + + /// + /// Gets the uppercase Base-16 format provider. + /// + public static readonly Base16FormatProvider Uppercase = new(1, nameof(Uppercase), "0123456789ABCDEF"); + + /// + /// Gets the lowercase Base-16 format provider. + /// + public static readonly Base16FormatProvider Lowercase = new(2, nameof(Lowercase), "0123456789abcdef"); + + /// + /// Initializes a new instance of the class. + /// + /// The value of the enumeration entry. + /// The name of the enumeration entry. + /// The alphabet of the format provider. + private Base16FormatProvider(int value, string name, string alphabet) : base(value, name) + { + Alphabet = alphabet; + } + + /// + /// Gets the alphabet of the current instance. + /// + public string Alphabet { get; } + + /// Gets an object that provides formatting services for the specified type. + /// An object that specifies the type of format object to return. + /// + /// Returns an instance of the object specified by , + /// if the implementation can supply that type of object; otherwise, . + /// + public object? GetFormat(Type? formatType) + { + return formatType == typeof(Base16FormatProvider) ? this : null; + } +} diff --git a/OnixLabs.Core/Text/Base32.Create.cs b/OnixLabs.Core/Text/Base32.Create.cs deleted file mode 100644 index ee9cd68..0000000 --- a/OnixLabs.Core/Text/Base32.Create.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base32 -{ - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base32 Create(byte[] value) - { - return new Base32(value); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base32 Create(ReadOnlySpan value) - { - return Create(value.ToArray()); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base32 Create(string value) - { - return Create(value.ToCharArray(), Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base32 Create(string value, Encoding encoding) - { - return Create(value.ToCharArray(), encoding); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base32 Create(char[] value) - { - return Create(value, Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base32 Create(char[] value, Encoding encoding) - { - return Create(encoding.GetBytes(value)); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base32 Create(ReadOnlySpan value) - { - return Create(value.ToArray(), Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base32 Create(ReadOnlySpan value, Encoding encoding) - { - return Create(value.ToArray(), encoding); - } -} diff --git a/OnixLabs.Core/Text/Base32.Equatable.cs b/OnixLabs.Core/Text/Base32.Equatable.cs index 56c1294..e9f993e 100644 --- a/OnixLabs.Core/Text/Base32.Equatable.cs +++ b/OnixLabs.Core/Text/Base32.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Linq; using OnixLabs.Core.Linq; @@ -21,13 +20,13 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base32 { /// - /// Checks for equality between the current instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// Returns if the object is equal to the current instance; otherwise, . + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . public bool Equals(Base32 other) { - return value.SequenceEqual(other.value); + return other.value.SequenceEqual(value); } /// @@ -46,26 +45,26 @@ public override bool Equals(object? obj) /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(value.GetContentHashCode()); + return value.GetContentHashCode(); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(Base32 left, Base32 right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(Base32 left, Base32 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base32.Format.cs b/OnixLabs.Core/Text/Base32.Format.cs index 0aef63a..447bd83 100644 --- a/OnixLabs.Core/Text/Base32.Format.cs +++ b/OnixLabs.Core/Text/Base32.Format.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base32.Parse.cs b/OnixLabs.Core/Text/Base32.Parse.cs index 9de5c71..a41403c 100644 --- a/OnixLabs.Core/Text/Base32.Parse.cs +++ b/OnixLabs.Core/Text/Base32.Parse.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,67 +19,62 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base32 { /// - /// Parses a Base-32 value into a value. + /// Parses the specified Base-32 encoded value into a value. /// - /// The Base-32 value to parse. - /// An object that provides format-specific information about the specified value. - /// Returns a new instance. + /// The Base-32 encoded value to parse. + /// The format provider that will be used to decode the specified value. + /// Returns a new instance, parsed from the specified Base-32 encoded value. public static Base32 Parse(string value, IFormatProvider? provider = null) { return Parse(value.AsSpan(), provider); } /// - /// Parses a Base-32 value into a value. + /// Parses the specified Base-32 encoded value into a value. /// - /// The Base-32 value to parse. - /// An object that provides format-specific information about the specified value. - /// Returns a new instance. + /// The Base-32 encoded value to parse. + /// The format provider that will be used to decode the specified value. + /// Returns a new instance, parsed from the specified Base-32 encoded value. public static Base32 Parse(ReadOnlySpan value, IFormatProvider? provider = null) { - if (TryParse(value, provider, out Base32 result)) return result; - throw new FormatException($"The input string '{value}' was not in a correct format."); + byte[] bytes = IBaseCodec.Base32.Decode(value, provider); + return new Base32(bytes); } /// - /// Tries to parse the specified Base-32 value into a value. + /// Tries to parse the specified Base-32 encoded value into a value. /// - /// The Base-32 value to parse. - /// An object that provides format-specific information about the specified value. + /// The Base-32 encoded value to parse. + /// The format provider that will be used to decode the specified value. /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. + /// A new instance, parsed from the specified Base-32 encoded value, + /// or the default value if the specified Base-32 encoded could not be parsed. /// - /// Returns if the specified value was parsed successfully; otherwise, . + /// Returns if the specified Base-32 value was decoded successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out Base32 result) { return TryParse(value.AsSpan(), provider, out result); } /// - /// Tries to parse the specified Base-32 value into a value. + /// Tries to parse the specified Base-32 encoded value into a value. /// - /// The Base-32 value to parse. - /// An object that provides format-specific information about the specified value. + /// The Base-32 encoded value to parse. + /// The format provider that will be used to decode the specified value. /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. + /// A new instance, parsed from the specified Base-32 encoded value, + /// or the default value if the specified Base-32 encoded could not be parsed. /// - /// Returns if the specified value was parsed successfully; otherwise, . + /// Returns if the specified Base-32 value was decoded successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base32 result) { - try + if (IBaseCodec.Base32.TryDecode(value, provider, out byte[] bytes)) { - Base32FormatInfo info = provider as Base32FormatInfo ?? Base32FormatInfo.Default; - bool padding = value.Contains('='); - byte[] bytes = Base32Codec.Decode(value, info.Alphabet, padding); - result = Create(bytes); + result = new Base32(bytes); return true; } - catch - { - result = Empty; - return false; - } + + result = default; + return false; } } diff --git a/OnixLabs.Core/Text/Base32.To.cs b/OnixLabs.Core/Text/Base32.To.cs index 5542564..0b38cc9 100644 --- a/OnixLabs.Core/Text/Base32.To.cs +++ b/OnixLabs.Core/Text/Base32.To.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,56 +13,46 @@ // limitations under the License. using System; -using System.Text; namespace OnixLabs.Core.Text; public readonly partial struct Base32 { /// - /// Returns a array that represents the current object. + /// Gets the underlying representation of the current instance. /// - /// Returns a array that represents the current object. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { return value.Copy(); } /// - /// Gets the plain-text representation of the current value, using the default . + /// Returns a that represents the current object. /// - /// Returns the plain-text representation of the current value, using the default . - public string ToPlainTextString() - { - return ToPlainTextString(Encoding.Default); - } - - /// - /// Gets the plain-text representation of the current value. - /// - /// The which will be used to obtain a from the current value. - /// Returns the plain-text representation of the current value. - public string ToPlainTextString(Encoding encoding) + /// Returns a that represents the current object. + public override string ToString() { - return encoding.GetString(value); + return ToString(Base32FormatProvider.Rfc4648); } /// - /// Returns a that represents the current object. + /// Formats the value of the current instance using the specified format. /// - /// Returns a that represents the current object. - public override string ToString() + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(IFormatProvider? formatProvider) { - return ToString(null); + return ToString(null, formatProvider); } /// /// Formats the value of the current instance using the specified format. /// - /// The format to use, or null to use the default format. + /// The format to use. /// The provider to use to format the value. /// The value of the current instance in the specified format. - public string ToString(string? format, IFormatProvider? formatProvider = null) + public string ToString(string? format, IFormatProvider? formatProvider) { return ToString(format.AsSpan(), formatProvider); } @@ -70,13 +60,11 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) /// /// Formats the value of the current instance using the specified format. /// - /// The format to use, or null to use the default format. + /// The format to use. /// The provider to use to format the value. /// The value of the current instance in the specified format. - public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider) { - Base32FormatInfo info = formatProvider as Base32FormatInfo ?? Base32FormatInfo.Default; - bool padding = char.ToUpperInvariant(format.IsEmpty || format.IsWhiteSpace() ? default : format[0]) == 'P'; - return Base32Codec.Encode(value, info.Alphabet, padding); + return IBaseCodec.Base32.Encode(value, formatProvider); } } diff --git a/OnixLabs.Core/Text/Base32.cs b/OnixLabs.Core/Text/Base32.cs index a25cc85..d19042d 100644 --- a/OnixLabs.Core/Text/Base32.cs +++ b/OnixLabs.Core/Text/Base32.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,24 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; + namespace OnixLabs.Core.Text; /// /// Represents a Base-32 value. /// -public readonly partial struct Base32 : IBaseRepresentation +/// The underlying value. +public readonly partial struct Base32(ReadOnlySpan value) : IBaseValue { - /// - /// The underlying value. - /// - private readonly byte[] value; + private readonly byte[] value = value.ToArray(); /// - /// Initializes a new instance of the struct. + /// Initializes a new default value. /// - /// The underlying value. - private Base32(byte[] value) + public Base32() : this([]) { - this.value = value.Copy(); } } diff --git a/OnixLabs.Core/Text/Base32Codec.cs b/OnixLabs.Core/Text/Base32Codec.cs index 1a0ed87..1db0cbd 100644 --- a/OnixLabs.Core/Text/Base32Codec.cs +++ b/OnixLabs.Core/Text/Base32Codec.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,15 +13,14 @@ // limitations under the License. using System; -using System.Collections.Generic; using System.Text; namespace OnixLabs.Core.Text; /// -/// Represents a Base-32 encoder/decoder. +/// Represents a codec for encoding and decoding Base-32 values. /// -internal static class Base32Codec +public sealed class Base32Codec : IBaseCodec { /// /// The Base-32 input data size. @@ -34,112 +33,195 @@ internal static class Base32Codec private const int OutputSize = 5; /// - /// Encode a byte array into a Base-32 string. + /// Encodes the specified value into a Base-32 representation. /// - /// The value to encode. - /// The Base-32 alphabet to use for encoding. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a Base-32 encoded string. - public static string Encode(IReadOnlyList value, string alphabet, bool padding) + /// The value to encode into a Base-32 representation. + /// The format provider that will be used to encode the specified value. + /// Returns a new Base-32 representation encoded from the specified value. + public string Encode(ReadOnlySpan value, IFormatProvider? provider = null) { - if (value.Count == 0) return string.Empty; - - StringBuilder builder = new(value.Count * InputSize / OutputSize); + if (TryEncode(value, provider, out string result)) return result; + throw new FormatException(IBaseCodec.EncodingFormatException); + } - int inputPosition = 0; - int inputSubPosition = 0; - byte outputPosition = 0; - int outputSubPosition = 0; + /// + /// Decodes the specified Base-32 representation into a . + /// + /// The Base-32 value to decode into a . + /// The format provider that will be used to decode the specified value. + /// Returns a new decoded from the specified value. + public byte[] Decode(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryDecode(value, provider, out byte[] result)) return result; + throw new FormatException(IBaseCodec.DecodingFormatException); + } - while (inputPosition < value.Count) + /// + /// Tries to encode the specified value into a Base-32 representation. + /// + /// The value to encode into a Base-32 representation. + /// The format provider that will be used to encode the specified value. + /// + /// A new Base-32 representation encoded from the specified value, + /// or an empty string if the specified value could not be encoded. + /// + /// Returns if the specified value was encoded successfully; otherwise, . + public bool TryEncode(ReadOnlySpan value, IFormatProvider? provider, out string result) + { + try { - int availableBits = Math.Min(InputSize - inputSubPosition, OutputSize - outputSubPosition); - - outputPosition <<= availableBits; - outputPosition |= (byte)(value[inputPosition] >> (InputSize - (inputSubPosition + availableBits))); - inputSubPosition += availableBits; + if (value.IsEmpty) + { + result = string.Empty; + return true; + } - if (inputSubPosition >= InputSize) + if (provider is not null && provider is not Base32FormatProvider) { - inputPosition++; - inputSubPosition = 0; + result = string.Empty; + return false; } - outputSubPosition += availableBits; + Base32FormatProvider formatProvider = provider as Base32FormatProvider ?? Base32FormatProvider.Rfc4648; + StringBuilder builder = new(value.Length * InputSize / OutputSize); - if (outputSubPosition < OutputSize) continue; + int inputPosition = 0; + int inputSubPosition = 0; + byte outputPosition = 0; + int outputSubPosition = 0; - outputPosition &= 0x1F; - builder.Append(alphabet[outputPosition]); - outputSubPosition = 0; - } + while (inputPosition < value.Length) + { + int availableBits = Math.Min(InputSize - inputSubPosition, OutputSize - outputSubPosition); + + outputPosition <<= availableBits; + outputPosition |= (byte)(value[inputPosition] >> (InputSize - (inputSubPosition + availableBits))); + inputSubPosition += availableBits; - if (outputSubPosition <= 0) return builder.ToString(); + if (inputSubPosition >= InputSize) + { + inputPosition++; + inputSubPosition = 0; + } - outputPosition <<= (OutputSize - outputSubPosition); - outputPosition &= 0x1F; - builder.Append(alphabet[outputPosition]); + outputSubPosition += availableBits; + + if (outputSubPosition < OutputSize) continue; + + outputPosition &= 0x1F; + builder.Append(formatProvider.Alphabet[outputPosition]); + outputSubPosition = 0; + } + + if (outputSubPosition <= 0) + { + result = builder.ToString(); + return true; + } + + outputPosition <<= (OutputSize - outputSubPosition); + outputPosition &= 0x1F; + builder.Append(formatProvider.Alphabet[outputPosition]); - while (padding && builder.Length % InputSize != 0) builder.Append('='); + while (formatProvider.IsPadded && builder.Length % InputSize != 0) builder.Append('='); - return builder.ToString(); + result = builder.ToString(); + return true; + } + catch + { + result = string.Empty; + return false; + } } /// - /// Decodes a Base-32 into a byte array. + /// Tries to decode the specified Base-32 representation into a . /// - /// The value to decode. - /// The Base-32 alphabet to use for decoding. - /// Determines whether padding should be applied for Base-32 encoding and decoding operations. - /// Returns a byte array. - /// If the Base-32 string format is invalid. - public static byte[] Decode(ReadOnlySpan value, string alphabet, bool padding) + /// The Base-32 value to decode into a . + /// The format provider that will be used to decode the specified value. + /// + /// A new decoded from the specified value, + /// or an empty if the specified value could not be decoded. + /// + /// Returns if the specified value was decoded successfully; otherwise, . + public bool TryDecode(ReadOnlySpan value, IFormatProvider? provider, out byte[] result) { - if (value == string.Empty) return []; + try + { + if (value.IsEmpty) + { + result = []; + return true; + } - if (padding && value.Length % InputSize != 0) - throw new FormatException("Base32 string is invalid. Insufficient padding has been applied."); + if (provider is not null && provider is not Base32FormatProvider) + { + result = []; + return false; + } - ReadOnlySpan valueWithoutPadding = padding ? value.TrimEnd('=') : value; + Base32FormatProvider formatProvider = provider as Base32FormatProvider ?? Base32FormatProvider.Rfc4648; - byte[] outputBytes = new byte[valueWithoutPadding.Length * OutputSize / InputSize]; + if (formatProvider.IsPadded && value.Length % InputSize != 0) + { + result = []; + return false; + } - if (outputBytes.Length == 0) - throw new FormatException("Base32 string is invalid. Not enough data to construct byte array."); + ReadOnlySpan valueWithoutPadding = formatProvider.IsPadded ? value.TrimEnd('=') : value; - int inputPosition = 0; - int inputSubPosition = 0; - int outputPosition = 0; - int outputSubPosition = 0; + byte[] outputBytes = new byte[valueWithoutPadding.Length * OutputSize / InputSize]; - while (outputPosition < outputBytes.Length) - { - char character = valueWithoutPadding[inputPosition]; - int index = alphabet.IndexOf(character); + if (outputBytes.Length == 0) + { + result = []; + return false; + } - if (index < 0) - throw new FormatException($"Invalid Base32 character '{character}' at position {inputPosition}"); + int inputPosition = 0; + int inputSubPosition = 0; + int outputPosition = 0; + int outputSubPosition = 0; - int availableBits = Math.Min(OutputSize - inputSubPosition, InputSize - outputSubPosition); + while (outputPosition < outputBytes.Length) + { + char character = valueWithoutPadding[inputPosition]; + int index = formatProvider.Alphabet.IndexOf(character); - outputBytes[outputPosition] <<= availableBits; - outputBytes[outputPosition] |= (byte)(index >> (OutputSize - (inputSubPosition + availableBits))); - outputSubPosition += availableBits; + if (index < 0) + { + result = []; + return false; + } - if (outputSubPosition >= InputSize) - { - outputPosition++; - outputSubPosition = 0; - } + int availableBits = Math.Min(OutputSize - inputSubPosition, InputSize - outputSubPosition); - inputSubPosition += availableBits; + outputBytes[outputPosition] <<= availableBits; + outputBytes[outputPosition] |= (byte)(index >> (OutputSize - (inputSubPosition + availableBits))); + outputSubPosition += availableBits; - if (inputSubPosition < OutputSize) continue; + if (outputSubPosition >= InputSize) + { + outputPosition++; + outputSubPosition = 0; + } - inputPosition++; - inputSubPosition = 0; - } + inputSubPosition += availableBits; + + if (inputSubPosition < OutputSize) continue; - return outputBytes; + inputPosition++; + inputSubPosition = 0; + } + + result = outputBytes; + return true; + } + catch + { + result = []; + return false; + } } } diff --git a/OnixLabs.Core/Text/Base32FormatInfo.cs b/OnixLabs.Core/Text/Base32FormatInfo.cs deleted file mode 100644 index 7b8eac9..0000000 --- a/OnixLabs.Core/Text/Base32FormatInfo.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Core.Text; - -/// -/// Represents Base-32 formatting information. -/// -public sealed class Base32FormatInfo : IFormatProvider -{ - /// - /// The default (RFC-4648) Base-32 alphabet. - /// - public static Base32FormatInfo Default => new(nameof(Default), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"); - - /// - /// The Z-Base-32 alphabet. - /// - public static Base32FormatInfo ZBase32 => new(nameof(ZBase32), "ybndrfg8ejkmcpqxot1uwisza345h769"); - - /// - /// The Geohash Base-32 alphabet. - /// - public static Base32FormatInfo GeoHash => new(nameof(GeoHash), "0123456789bcdefghjkmnpqrstuvwxyz"); - - /// - /// The Crockford Base-32 alphabet. - /// - public static Base32FormatInfo Crockford => new(nameof(Crockford), "0123456789ABCDEFGHJKMNPQRSTVWXYZ"); - - /// - /// The Base-32 Hex alphabet. - /// - public static Base32FormatInfo Base32Hex => new(nameof(Base32Hex), "0123456789ABCDEFGHIJKLMNOPQRSTUV"); - - /// - /// Initializes a new instance of the class. - /// - /// The name of the Base-32 alphabet. - /// The alphabet that will be used for Base-32 encoding and decoding operations. - private Base32FormatInfo(string name, string alphabet) - { - Name = name; - Alphabet = alphabet; - } - - /// - /// Gets the name of the Base-32 alphabet. - /// - public string Name { get; } - - /// - /// Gets the alphabet that will be used for Base-32 encoding and decoding operations. - /// - public string Alphabet { get; } - - /// Returns an object that provides formatting services for the specified type. - /// An object that specifies the type of format object to return. - /// - /// Returns an instance of the object specified by , - /// if the implementation can supply that type of object; otherwise, . - /// - public object? GetFormat(Type? formatType) - { - return formatType == typeof(Base32FormatInfo) ? this : null; - } -} diff --git a/OnixLabs.Core/Text/Base32FormatProvider.cs b/OnixLabs.Core/Text/Base32FormatProvider.cs new file mode 100644 index 0000000..28c0d72 --- /dev/null +++ b/OnixLabs.Core/Text/Base32FormatProvider.cs @@ -0,0 +1,107 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +/// +/// Represents a Base-32 format provider. +/// +public sealed class Base32FormatProvider : Enumeration, IFormatProvider +{ + /// + /// Gets the RFC 4648 Base-32 format provider. + /// + public static readonly Base32FormatProvider Rfc4648 = new(0, nameof(Rfc4648), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", false); + + /// + /// Gets the Z-Base-32 format provider. + /// + public static readonly Base32FormatProvider ZBase32 = new(1, nameof(ZBase32), "ybndrfg8ejkmcpqxot1uwisza345h769", false); + + /// + /// Gets the GeoHash Base-32 format provider. + /// + public static readonly Base32FormatProvider GeoHash = new(2, nameof(GeoHash), "0123456789bcdefghjkmnpqrstuvwxyz", false); + + /// + /// Gets the Crockford Base-32 format provider. + /// + public static readonly Base32FormatProvider Crockford = new(3, nameof(Crockford), "0123456789ABCDEFGHJKMNPQRSTVWXYZ", false); + + /// + /// Gets the Base-32 Hex format provider. + /// + public static readonly Base32FormatProvider Base32Hex = new(4, nameof(Base32Hex), "0123456789ABCDEFGHIJKLMNOPQRSTUV", false); + + /// + /// Gets the RFC 4648 Base-32 format provider. + /// + public static readonly Base32FormatProvider PaddedRfc4648 = new(5, nameof(PaddedRfc4648), "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567", true); + + /// + /// Gets the Z-Base-32 format provider. + /// + public static readonly Base32FormatProvider PaddedZBase32 = new(6, nameof(PaddedZBase32), "ybndrfg8ejkmcpqxot1uwisza345h769", true); + + /// + /// Gets the GeoHash Base-32 format provider. + /// + public static readonly Base32FormatProvider PaddedGeoHash = new(7, nameof(PaddedGeoHash), "0123456789bcdefghjkmnpqrstuvwxyz", true); + + /// + /// Gets the Crockford Base-32 format provider. + /// + public static readonly Base32FormatProvider PaddedCrockford = new(8, nameof(PaddedCrockford), "0123456789ABCDEFGHJKMNPQRSTVWXYZ", true); + + /// + /// Gets the Base-32 Hex format provider. + /// + public static readonly Base32FormatProvider PaddedBase32Hex = new(9, nameof(PaddedBase32Hex), "0123456789ABCDEFGHIJKLMNOPQRSTUV", true); + + /// + /// Initializes a new instance of the class. + /// + /// The value of the enumeration entry. + /// The name of the enumeration entry. + /// The alphabet of the format provider. + /// A value indicating whether the format provider uses padding. + private Base32FormatProvider(int value, string name, string alphabet, bool isPadded) : base(value, name) + { + Alphabet = alphabet; + IsPadded = isPadded; + } + + /// + /// Gets the alphabet of the current instance. + /// + public string Alphabet { get; } + + /// + /// Gets a value indicating whether the current instance uses padding. + /// + public bool IsPadded { get; } + + /// Gets an object that provides formatting services for the specified type. + /// An object that specifies the type of format object to return. + /// + /// Returns an instance of the object specified by , + /// if the implementation can supply that type of object; otherwise, . + /// + public object? GetFormat(Type? formatType) + { + return formatType == typeof(Base32FormatProvider) ? this : null; + } +} diff --git a/OnixLabs.Core/Text/Base58.Checksum.cs b/OnixLabs.Core/Text/Base58.Checksum.cs deleted file mode 100644 index aae55c4..0000000 --- a/OnixLabs.Core/Text/Base58.Checksum.cs +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; -using System.Security.Cryptography; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base58 -{ - /// - /// The size of a Base-58 checksum. - /// - private const int ChecksumSize = 4; - - /// - /// Computes a Base-58 checksum. - /// - /// The value for which to compute a Base-58 checksum. - /// Returns the computed Base-58 checksum. - private static byte[] ComputeChecksum(byte[] value) - { - using HashAlgorithm algorithm = SHA256.Create(); - - byte[] hashedValue = algorithm.ComputeHash(value); - byte[] checksum = algorithm.ComputeHash(hashedValue); - byte[] result = new byte[ChecksumSize]; - - Buffer.BlockCopy(checksum, 0, result, 0, result.Length); - - return result; - } - - /// - /// Adds a checksum to the specified byte array. - /// - /// The value for which to add a checksum. - /// Returns the original value with a checksum. - private static byte[] AddChecksum(byte[] value) - { - byte[] checksum = ComputeChecksum(value); - return value.ConcatenateWith(checksum); - } - - /// - /// Removes a checksum from the specified byte array. - /// - /// The value for which to remove a checksum. - /// Returns the original value without a checksum. - private static byte[] RemoveChecksum(byte[] value) - { - return value.Copy(0, value.Length - ChecksumSize); - } - - /// - /// Gets a checksum from the specified byte array. - /// - /// The value from which to obtain a checksum. - /// Returns a checksum from the specified byte array. - private static byte[] GetChecksum(byte[] value) - { - return value.Copy(value.Length - ChecksumSize - 1, ChecksumSize); - } - - /// - /// Verifies a Base-58 checksum. - /// - /// The value for which to verify its checksum. - /// If the Base-58 checksum is invalid. - private static void VerifyChecksum(byte[] value) - { - byte[] valueWithoutChecksum = RemoveChecksum(value); - byte[] originalChecksum = GetChecksum(value); - byte[] computedChecksum = ComputeChecksum(valueWithoutChecksum); - - if (!originalChecksum.SequenceEqual(computedChecksum)) - throw new FormatException("Base-58 checksum is invalid."); - } -} diff --git a/OnixLabs.Core/Text/Base58.Create.cs b/OnixLabs.Core/Text/Base58.Create.cs deleted file mode 100644 index 65a6ee3..0000000 --- a/OnixLabs.Core/Text/Base58.Create.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base58 -{ - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base58 Create(byte[] value) - { - return new Base58(value); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base58 Create(ReadOnlySpan value) - { - return Create(value.ToArray()); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base58 Create(string value) - { - return Create(value.ToCharArray(), Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base58 Create(string value, Encoding encoding) - { - return Create(value.ToCharArray(), encoding); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base58 Create(char[] value) - { - return Create(value, Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base58 Create(char[] value, Encoding encoding) - { - return Create(encoding.GetBytes(value)); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base58 Create(ReadOnlySpan value) - { - return Create(value.ToArray(), Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base58 Create(ReadOnlySpan value, Encoding encoding) - { - return Create(value.ToArray(), encoding); - } -} diff --git a/OnixLabs.Core/Text/Base58.Equatable.cs b/OnixLabs.Core/Text/Base58.Equatable.cs index e75e43a..40020c3 100644 --- a/OnixLabs.Core/Text/Base58.Equatable.cs +++ b/OnixLabs.Core/Text/Base58.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,9 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Linq; -using System.Text; using OnixLabs.Core.Linq; namespace OnixLabs.Core.Text; @@ -22,13 +20,13 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base58 { /// - /// Checks for equality between the current instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// Returns if the object is equal to the current instance; otherwise, . + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . public bool Equals(Base58 other) { - return value.SequenceEqual(other.value); + return other.value.SequenceEqual(value); } /// @@ -47,26 +45,26 @@ public override bool Equals(object? obj) /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(value.GetContentHashCode()); + return value.GetContentHashCode(); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(Base58 left, Base58 right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(Base58 left, Base58 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base58.Format.cs b/OnixLabs.Core/Text/Base58.Format.cs index 0624fd7..7f63a64 100644 --- a/OnixLabs.Core/Text/Base58.Format.cs +++ b/OnixLabs.Core/Text/Base58.Format.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base58.Parse.cs b/OnixLabs.Core/Text/Base58.Parse.cs index 978f083..a09da23 100644 --- a/OnixLabs.Core/Text/Base58.Parse.cs +++ b/OnixLabs.Core/Text/Base58.Parse.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,134 +19,62 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base58 { /// - /// Parses a Base-58 value into a value. + /// Parses the specified Base-58 encoded value into a value. /// - /// The Base-58 value to parse. - /// An object that provides format-specific information about the specified value. - /// Returns a new instance. + /// The Base-58 encoded value to parse. + /// The format provider that will be used to decode the specified value. + /// Returns a new instance, parsed from the specified Base-58 encoded value. public static Base58 Parse(string value, IFormatProvider? provider = null) { return Parse(value.AsSpan(), provider); } /// - /// Parses a Base-58 value into a value. + /// Parses the specified Base-58 encoded value into a value. /// - /// The Base-58 value to parse. - /// An object that provides format-specific information about the specified value. - /// Returns a new instance. + /// The Base-58 encoded value to parse. + /// The format provider that will be used to decode the specified value. + /// Returns a new instance, parsed from the specified Base-58 encoded value. public static Base58 Parse(ReadOnlySpan value, IFormatProvider? provider = null) { - if (TryParse(value, provider, out Base58 result)) return result; - throw new FormatException($"The input string '{value}' was not in a correct format."); + byte[] bytes = IBaseCodec.Base58.Decode(value, provider); + return new Base58(bytes); } /// - /// Parses a Base-58 value with a checksum into a value. + /// Tries to parse the specified Base-58 encoded value into a value. /// - /// The Base-58 value to parse. - /// An object that provides format-specific information about the specified value. - /// Returns a new instance. - public static Base58 ParseWithChecksum(string value, IFormatProvider? provider = null) - { - return ParseWithChecksum(value.AsSpan(), provider); - } - - /// - /// Parses a Base-58 value with a checksum into a value. - /// - /// The Base-58 value to parse. - /// An object that provides format-specific information about the specified value. - /// Returns a new instance. - public static Base58 ParseWithChecksum(ReadOnlySpan value, IFormatProvider? provider = null) - { - if (TryParseWithChecksum(value, provider, out Base58 result)) return result; - throw new FormatException($"The input string '{value}' was not in a correct format."); - } - - /// - /// Tries to parse the specified Base-58 value into a value. - /// - /// The Base-58 value to parse. - /// An object that provides format-specific information about the specified value. + /// The Base-58 encoded value to parse. + /// The format provider that will be used to decode the specified value. /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. + /// A new instance, parsed from the specified Base-58 encoded value, + /// or the default value if the specified Base-58 encoded could not be parsed. /// - /// Returns if the specified value was parsed successfully; otherwise, . + /// Returns if the specified Base-58 value was decoded successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out Base58 result) { return TryParse(value.AsSpan(), provider, out result); } /// - /// Tries to parse the specified Base-58 value into a value. + /// Tries to parse the specified Base-58 encoded value into a value. /// - /// The Base-58 value to parse. - /// An object that provides format-specific information about the specified value. + /// The Base-58 encoded value to parse. + /// The format provider that will be used to decode the specified value. /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. + /// A new instance, parsed from the specified Base-58 encoded value, + /// or the default value if the specified Base-58 encoded could not be parsed. /// - /// Returns if the specified value was parsed successfully; otherwise, . + /// Returns if the specified Base-58 value was decoded successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base58 result) { - try + if (IBaseCodec.Base58.TryDecode(value, provider, out byte[] bytes)) { - Base58FormatInfo info = provider as Base58FormatInfo ?? Base58FormatInfo.Default; - byte[] bytes = Base58Codec.Decode(value, info.Alphabet); - result = Create(bytes); + result = new Base58(bytes); return true; } - catch - { - result = Empty; - return false; - } - } - - /// - /// Tries to parse the specified Base-58 value with a checksum into a value. - /// - /// The Base-58 value to parse. - /// An object that provides format-specific information about the specified value. - /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. - /// - /// Returns if the specified value was parsed successfully; otherwise, . - public static bool TryParseWithChecksum(string? value, IFormatProvider? provider, out Base58 result) - { - return TryParseWithChecksum(value.AsSpan(), provider, out result); - } - - /// - /// Tries to parse the specified Base-58 value with a checksum into a value. - /// - /// The Base-58 value to parse. - /// An object that provides format-specific information about the specified value. - /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. - /// - /// Returns if the specified value was parsed successfully; otherwise, . - public static bool TryParseWithChecksum(ReadOnlySpan value, IFormatProvider? provider, out Base58 result) - { - try - { - Base58FormatInfo info = provider as Base58FormatInfo ?? Base58FormatInfo.Default; - byte[] bytes = Base58Codec.Decode(value, info.Alphabet); - byte[] bytesWithoutChecksum = RemoveChecksum(bytes); - - VerifyChecksum(bytes); - result = Create(bytesWithoutChecksum); - return true; - } - catch - { - result = Empty; - return false; - } + result = default; + return false; } } diff --git a/OnixLabs.Core/Text/Base58.To.cs b/OnixLabs.Core/Text/Base58.To.cs index 4d0c096..d3f2ae9 100644 --- a/OnixLabs.Core/Text/Base58.To.cs +++ b/OnixLabs.Core/Text/Base58.To.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,56 +13,46 @@ // limitations under the License. using System; -using System.Text; namespace OnixLabs.Core.Text; public readonly partial struct Base58 { /// - /// Returns a array that represents the current object. + /// Gets the underlying representation of the current instance. /// - /// Returns a array that represents the current object. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { return value.Copy(); } /// - /// Gets the plain-text representation of the current value, using the default . + /// Returns a that represents the current object. /// - /// Returns the plain-text representation of the current value, using the default . - public string ToPlainTextString() - { - return ToPlainTextString(Encoding.Default); - } - - /// - /// Gets the plain-text representation of the current value. - /// - /// The which will be used to obtain a from the current value. - /// Returns the plain-text representation of the current value. - public string ToPlainTextString(Encoding encoding) + /// Returns a that represents the current object. + public override string ToString() { - return encoding.GetString(value); + return ToString(Base58FormatProvider.Bitcoin); } /// - /// Returns a that represents the current object. + /// Formats the value of the current instance using the specified format. /// - /// Returns a that represents the current object. - public override string ToString() + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(IFormatProvider? formatProvider) { - return ToString(null); + return ToString(null, formatProvider); } /// /// Formats the value of the current instance using the specified format. /// - /// The format to use, or null to use the default format. + /// The format to use. /// The provider to use to format the value. /// The value of the current instance in the specified format. - public string ToString(string? format, IFormatProvider? formatProvider = null) + public string ToString(string? format, IFormatProvider? formatProvider) { return ToString(format.AsSpan(), formatProvider); } @@ -70,12 +60,11 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) /// /// Formats the value of the current instance using the specified format. /// - /// The format to use, or null to use the default format. + /// The format to use. /// The provider to use to format the value. /// The value of the current instance in the specified format. - public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider) { - Base58FormatInfo info = formatProvider as Base58FormatInfo ?? Base58FormatInfo.Default; - return Base58Codec.Encode(value, info.Alphabet); + return IBaseCodec.Base58.Encode(value, formatProvider); } } diff --git a/OnixLabs.Core/Text/Base58.cs b/OnixLabs.Core/Text/Base58.cs index 531931f..3bbfc8a 100644 --- a/OnixLabs.Core/Text/Base58.cs +++ b/OnixLabs.Core/Text/Base58.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,24 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; + namespace OnixLabs.Core.Text; /// /// Represents a Base-58 value. /// -public readonly partial struct Base58 : IBaseRepresentation +/// The underlying value. +public readonly partial struct Base58(ReadOnlySpan value) : IBaseValue { - /// - /// The underlying value. - /// - private readonly byte[] value; + private readonly byte[] value = value.ToArray(); /// - /// Initializes a new instance of the struct. + /// Initializes a new default value. /// - /// The underlying value. - private Base58(byte[] value) + public Base58() : this([]) { - this.value = value.Copy(); } } diff --git a/OnixLabs.Core/Text/Base58Codec.cs b/OnixLabs.Core/Text/Base58Codec.cs index 0e9a34c..8b4c15e 100644 --- a/OnixLabs.Core/Text/Base58Codec.cs +++ b/OnixLabs.Core/Text/Base58Codec.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,70 +21,150 @@ namespace OnixLabs.Core.Text; /// -/// Represents a Base-58 encoder/decoder. +/// Represents a codec for encoding and decoding Base-58 values. /// -internal static class Base58Codec +public sealed class Base58Codec : IBaseCodec { /// - /// Encode a byte array into a Base-58 string. + /// Encodes the specified value into a Base-58 representation. /// - /// The value to encode. - /// The Base-58 alphabet to use for encoding. - /// Returns a Base-58 encoded string. - public static string Encode(IReadOnlyList value, string alphabet) + /// The value to encode into a Base-58 representation. + /// The format provider that will be used to encode the specified value. + /// Returns a new Base-58 representation encoded from the specified value. + public string Encode(ReadOnlySpan value, IFormatProvider? provider = null) { - BigInteger data = value.Aggregate(BigInteger.Zero, (a, b) => a * 256 + b); - StringBuilder result = new(); + if (TryEncode(value, provider, out string result)) return result; + throw new FormatException(IBaseCodec.EncodingFormatException); + } - while (data > 0) + /// + /// Decodes the specified Base-58 representation into a . + /// + /// The Base-58 value to decode into a . + /// The format provider that will be used to decode the specified value. + /// Returns a new decoded from the specified value. + public byte[] Decode(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryDecode(value, provider, out byte[] result)) return result; + throw new FormatException(IBaseCodec.DecodingFormatException); + } + + /// + /// Tries to encode the specified value into a Base-58 representation. + /// + /// The value to encode into a Base-58 representation. + /// The format provider that will be used to encode the specified value. + /// + /// A new Base-58 representation encoded from the specified value, + /// or an empty string if the specified value could not be encoded. + /// + /// Returns if the specified value was encoded successfully; otherwise, . + public bool TryEncode(ReadOnlySpan value, IFormatProvider? provider, out string result) + { + try { - BigInteger remainder = data % 58; - data /= 58; - result.Insert(0, alphabet[(int)remainder]); - } + if (value.IsEmpty) + { + result = string.Empty; + return true; + } + + if (provider is not null && provider is not Base58FormatProvider) + { + result = string.Empty; + return false; + } + + Base58FormatProvider formatProvider = provider as Base58FormatProvider ?? Base58FormatProvider.Bitcoin; + StringBuilder builder = new(); + BigInteger data = BigInteger.Zero; + foreach (byte b in value) data = data * 256 + b; + + while (data > 0) + { + BigInteger remainder = data % 58; + data /= 58; + builder.Insert(0, formatProvider.Alphabet[(int)remainder]); + } - for (int index = 0; index < value.Count && value[index] == 0; index++) result.Insert(0, '1'); + for (int index = 0; index < value.Length && value[index] == 0; index++) builder.Insert(0, '1'); - return result.ToString(); + result = builder.ToString(); + return true; + } + catch + { + result = string.Empty; + return false; + } } /// - /// Decodes a Base-58 into a byte array. + /// Tries to decode the specified Base-58 representation into a . /// - /// The value to decode. - /// The Base-58 alphabet to use for decoding. - /// Returns a byte array. - /// If the Base-58 string format is invalid. - public static byte[] Decode(ReadOnlySpan value, string alphabet) + /// The Base-58 value to decode into a . + /// The format provider that will be used to decode the specified value. + /// + /// A new decoded from the specified value, + /// or an empty if the specified value could not be decoded. + /// + /// Returns if the specified value was decoded successfully; otherwise, . + public bool TryDecode(ReadOnlySpan value, IFormatProvider? provider, out byte[] result) { - BigInteger data = BigInteger.Zero; - - for (int index = 0; index < value.Length; index++) + try { - char character = value[index]; - int characterIndex = alphabet.IndexOf(character); + if (value.IsEmpty) + { + result = []; + return true; + } - if (characterIndex < 0) - throw new FormatException($"Invalid Base58 character '{character}' at position {index}"); + if (provider is not null && provider is not Base58FormatProvider) + { + result = []; + return false; + } - data = data * 58 + characterIndex; - } + Base58FormatProvider formatProvider = provider as Base58FormatProvider ?? Base58FormatProvider.Bitcoin; + + BigInteger data = BigInteger.Zero; + + foreach (char character in value) + { + int characterIndex = formatProvider.Alphabet.IndexOf(character); - int leadingZeroCount = value - .ToArray() - .TakeWhile(character => character == '1') - .Count(); + if (characterIndex < 0) + { + result = []; + return false; + } - IEnumerable leadingZeros = Enumerable - .Repeat(byte.MinValue, leadingZeroCount); + data = data * 58 + characterIndex; + } - IEnumerable bytesWithoutLeadingZeros = data - .ToByteArray() - .Reverse() - .SkipWhile(byteValue => byteValue == 0); + int leadingZeroCount = value + .ToArray() + .TakeWhile(character => character == '1') + .Count(); - return leadingZeros - .Concat(bytesWithoutLeadingZeros) - .ToArray(); + IEnumerable leadingZeros = Enumerable + .Repeat(byte.MinValue, leadingZeroCount); + + IEnumerable bytesWithoutLeadingZeros = data + .ToByteArray() + .Reverse() + .SkipWhile(byteValue => byteValue == 0); + + result = leadingZeros + .Concat(bytesWithoutLeadingZeros) + .ToArray(); + + return true; + } + catch + { + result = []; + return false; + } } } diff --git a/OnixLabs.Core/Text/Base58FormatInfo.cs b/OnixLabs.Core/Text/Base58FormatInfo.cs deleted file mode 100644 index 344d66e..0000000 --- a/OnixLabs.Core/Text/Base58FormatInfo.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Core.Text; - -/// -/// Represents Base-58 formatting information. -/// -public sealed class Base58FormatInfo : IFormatProvider -{ - /// - /// The default Base-58 alphabet, which is the same as Bitcoin's Base-58 alphabet. - /// - public static Base58FormatInfo Default => new(nameof(Default), "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"); - - /// - /// The Ripple Base-58 alphabet. - /// - public static Base58FormatInfo Ripple => new(nameof(Ripple), "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"); - - /// - /// The Flickr Base-58 alphabet. - /// - public static Base58FormatInfo Flickr => new(nameof(Flickr), "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"); - - /// - /// Initializes a new instance of the class. - /// - /// The name of the Base-58 alphabet. - /// The alphabet that will be used for Base-58 encoding and decoding operations. - private Base58FormatInfo(string name, string alphabet) - { - Name = name; - Alphabet = alphabet; - } - - /// - /// Gets the name of the Base-58 alphabet. - /// - public string Name { get; } - - /// - /// Gets the alphabet that will be used for Base-58 encoding and decoding operations. - /// - public string Alphabet { get; } - - /// Returns an object that provides formatting services for the specified type. - /// An object that specifies the type of format object to return. - /// An instance of the object specified by , if the implementation can supply that type of object; otherwise, . - public object? GetFormat(Type? formatType) - { - return formatType == typeof(Base58FormatInfo) ? this : null; - } -} diff --git a/OnixLabs.Core/Text/Base58FormatProvider.cs b/OnixLabs.Core/Text/Base58FormatProvider.cs new file mode 100644 index 0000000..360e9d2 --- /dev/null +++ b/OnixLabs.Core/Text/Base58FormatProvider.cs @@ -0,0 +1,66 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +/// +/// Represents a Base-58 format provider. +/// +public sealed class Base58FormatProvider : Enumeration, IFormatProvider +{ + /// + /// Gets the Bitcoin Base-58 format provider. + /// This is also the same format used by Monero and IPFS. + /// + public static readonly Base58FormatProvider Bitcoin = new(0, nameof(Bitcoin), "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"); + + /// + /// Gets the Flickr Base-58 format provider. + /// + public static readonly Base58FormatProvider Flickr = new(1, nameof(Flickr), "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"); + + /// + /// Gets the Ripple Base-58 format provider. + /// + public static readonly Base58FormatProvider Ripple = new(2, nameof(Ripple), "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz"); + + /// + /// Initializes a new instance of the class. + /// + /// The value of the enumeration entry. + /// The name of the enumeration entry. + /// The alphabet of the format provider. + private Base58FormatProvider(int value, string name, string alphabet) : base(value, name) + { + Alphabet = alphabet; + } + + /// + /// Gets the alphabet of the current instance. + /// + public string Alphabet { get; } + + /// Gets an object that provides formatting services for the specified type. + /// An object that specifies the type of format object to return. + /// + /// Returns an instance of the object specified by , + /// if the implementation can supply that type of object; otherwise, . + /// + public object? GetFormat(Type? formatType) + { + return formatType == typeof(Base58FormatProvider) ? this : null; + } +} diff --git a/OnixLabs.Core/Text/Base64.Create.cs b/OnixLabs.Core/Text/Base64.Create.cs deleted file mode 100644 index 43fac8b..0000000 --- a/OnixLabs.Core/Text/Base64.Create.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Text; - -namespace OnixLabs.Core.Text; - -public readonly partial struct Base64 -{ - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base64 Create(byte[] value) - { - return new Base64(value); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base64 Create(ReadOnlySpan value) - { - return Create(value.ToArray()); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base64 Create(string value) - { - return Create(value.ToCharArray(), Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base64 Create(string value, Encoding encoding) - { - return Create(value.ToCharArray(), encoding); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base64 Create(char[] value) - { - return Create(value, Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base64 Create(char[] value, Encoding encoding) - { - return Create(encoding.GetBytes(value)); - } - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static Base64 Create(ReadOnlySpan value) - { - return Create(value.ToArray(), Encoding.Default); - } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static Base64 Create(ReadOnlySpan value, Encoding encoding) - { - return Create(value.ToArray(), encoding); - } -} diff --git a/OnixLabs.Core/Text/Base64.Equatable.cs b/OnixLabs.Core/Text/Base64.Equatable.cs index 1818dbe..709c1af 100644 --- a/OnixLabs.Core/Text/Base64.Equatable.cs +++ b/OnixLabs.Core/Text/Base64.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Linq; using OnixLabs.Core.Linq; @@ -21,13 +20,13 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base64 { /// - /// Checks for equality between the current instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// Returns if the object is equal to the current instance; otherwise, . + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . public bool Equals(Base64 other) { - return value.SequenceEqual(other.value); + return other.value.SequenceEqual(value); } /// @@ -46,26 +45,26 @@ public override bool Equals(object? obj) /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(value.GetContentHashCode()); + return value.GetContentHashCode(); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(Base64 left, Base64 right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// Returns if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(Base64 left, Base64 right) { return !Equals(left, right); diff --git a/OnixLabs.Core/Text/Base64.Format.cs b/OnixLabs.Core/Text/Base64.Format.cs index 4756003..3f3345a 100644 --- a/OnixLabs.Core/Text/Base64.Format.cs +++ b/OnixLabs.Core/Text/Base64.Format.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/Base64.Parse.cs b/OnixLabs.Core/Text/Base64.Parse.cs index 9d87d12..89a0bb5 100644 --- a/OnixLabs.Core/Text/Base64.Parse.cs +++ b/OnixLabs.Core/Text/Base64.Parse.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -19,77 +19,62 @@ namespace OnixLabs.Core.Text; public readonly partial struct Base64 { /// - /// Parses a Base-64 value into a value. + /// Parses the specified Base-64 encoded value into a value. /// - /// The Base-64 value to parse. - /// - /// An object that provides format-specific information about the specified value. - /// The parameter is ignored by the current implementation of . - /// - /// Returns a new instance. + /// The Base-64 encoded value to parse. + /// The format provider that will be used to decode the specified value. + /// Returns a new instance, parsed from the specified Base-64 encoded value. public static Base64 Parse(string value, IFormatProvider? provider = null) { return Parse(value.AsSpan(), provider); } /// - /// Parses a Base-64 value into a value. + /// Parses the specified Base-64 encoded value into a value. /// - /// The Base-64 value to parse. - /// - /// An object that provides format-specific information about the specified value. - /// The parameter is ignored by the current implementation of . - /// - /// Returns a new instance. + /// The Base-64 encoded value to parse. + /// The format provider that will be used to decode the specified value. + /// Returns a new instance, parsed from the specified Base-64 encoded value. public static Base64 Parse(ReadOnlySpan value, IFormatProvider? provider = null) { - if (TryParse(value, provider, out Base64 result)) return result; - throw new FormatException($"The input string '{value}' was not in a correct format."); + byte[] bytes = IBaseCodec.Base64.Decode(value, provider); + return new Base64(bytes); } /// - /// Tries to parse the specified Base-64 value into a value. + /// Tries to parse the specified Base-64 encoded value into a value. /// - /// The Base-64 value to parse. - /// - /// An object that provides format-specific information about the specified value. - /// The parameter is ignored by the current implementation of . - /// + /// The Base-64 encoded value to parse. + /// The format provider that will be used to decode the specified value. /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. + /// A new instance, parsed from the specified Base-64 encoded value, + /// or the default value if the specified Base-64 encoded could not be parsed. /// - /// Returns if the specified value was parsed successfully; otherwise, . + /// Returns if the specified Base-64 value was decoded successfully; otherwise, . public static bool TryParse(string? value, IFormatProvider? provider, out Base64 result) { return TryParse(value.AsSpan(), provider, out result); } /// - /// Tries to parse the specified Base-64 value into a value. + /// Tries to parse the specified Base-64 encoded value into a value. /// - /// The Base-64 value to parse. - /// - /// An object that provides format-specific information about the specified value. - /// The parameter is ignored by the current implementation of . - /// + /// The Base-64 encoded value to parse. + /// The format provider that will be used to decode the specified value. /// - /// On return, contains the result of parsing the specified value, - /// or the default value in the event that the specified value could not be parsed. + /// A new instance, parsed from the specified Base-64 encoded value, + /// or the default value if the specified Base-64 encoded could not be parsed. /// - /// Returns if the specified value was parsed successfully; otherwise, . + /// Returns if the specified Base-64 value was decoded successfully; otherwise, . public static bool TryParse(ReadOnlySpan value, IFormatProvider? provider, out Base64 result) { - try + if (IBaseCodec.Base64.TryDecode(value, provider, out byte[] bytes)) { - byte[] bytes = Convert.FromBase64String(value.ToString()); - result = Create(bytes); + result = new Base64(bytes); return true; } - catch - { - result = Empty; - return false; - } + + result = default; + return false; } } diff --git a/OnixLabs.Core/Text/Base64.To.cs b/OnixLabs.Core/Text/Base64.To.cs index 31fb122..4ba8048 100644 --- a/OnixLabs.Core/Text/Base64.To.cs +++ b/OnixLabs.Core/Text/Base64.To.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,56 +13,46 @@ // limitations under the License. using System; -using System.Text; namespace OnixLabs.Core.Text; public readonly partial struct Base64 { /// - /// Returns a array that represents the current object. + /// Gets the underlying representation of the current instance. /// - /// Returns a array that represents the current object. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { return value.Copy(); } /// - /// Gets the plain-text representation of the current value, using the default . + /// Returns a that represents the current object. /// - /// Returns the plain-text representation of the current value, using the default . - public string ToPlainTextString() - { - return ToPlainTextString(Encoding.Default); - } - - /// - /// Gets the plain-text representation of the current value. - /// - /// The which will be used to obtain a from the current value. - /// Returns the plain-text representation of the current value. - public string ToPlainTextString(Encoding encoding) + /// Returns a that represents the current object. + public override string ToString() { - return encoding.GetString(value); + return ToString(null); } /// - /// Returns a that represents the current object. + /// Formats the value of the current instance using the specified format. /// - /// Returns a that represents the current object. - public override string ToString() + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + public string ToString(IFormatProvider? formatProvider) { - return ToString(null); + return ToString(null, formatProvider); } /// /// Formats the value of the current instance using the specified format. /// - /// The format to use, or null to use the default format. + /// The format to use. /// The provider to use to format the value. /// The value of the current instance in the specified format. - public string ToString(string? format, IFormatProvider? formatProvider = null) + public string ToString(string? format, IFormatProvider? formatProvider) { return ToString(format.AsSpan(), formatProvider); } @@ -70,11 +60,11 @@ public string ToString(string? format, IFormatProvider? formatProvider = null) /// /// Formats the value of the current instance using the specified format. /// - /// The format to use, or null to use the default format. + /// The format to use. /// The provider to use to format the value. /// The value of the current instance in the specified format. - public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider = null) + public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider) { - return Convert.ToBase64String(value); + return IBaseCodec.Base64.Encode(value, formatProvider); } } diff --git a/OnixLabs.Core/Text/Base64.cs b/OnixLabs.Core/Text/Base64.cs index d4a4ef4..09d103f 100644 --- a/OnixLabs.Core/Text/Base64.cs +++ b/OnixLabs.Core/Text/Base64.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,24 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; + namespace OnixLabs.Core.Text; /// /// Represents a Base-64 value. /// -public readonly partial struct Base64 : IBaseRepresentation +/// The underlying value. +public readonly partial struct Base64(ReadOnlySpan value) : IBaseValue { - /// - /// The underlying value. - /// - private readonly byte[] value; + private readonly byte[] value = value.ToArray(); /// - /// Initializes a new instance of the struct. + /// Initializes a new default value. /// - /// The underlying value. - private Base64(byte[] value) + public Base64() : this([]) { - this.value = value.Copy(); } } diff --git a/OnixLabs.Core/Text/Base64Codec.cs b/OnixLabs.Core/Text/Base64Codec.cs new file mode 100644 index 0000000..38df383 --- /dev/null +++ b/OnixLabs.Core/Text/Base64Codec.cs @@ -0,0 +1,95 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +/// +/// Represents a codec for encoding and decoding Base-64 values. +/// +public sealed class Base64Codec : IBaseCodec +{ + /// + /// Encodes the specified value into a Base-64 representation. + /// + /// The value to encode into a Base-64 representation. + /// The format provider that will be used to encode the specified value. + /// Returns a new Base-64 representation encoded from the specified value. + public string Encode(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryEncode(value, provider, out string result)) return result; + throw new FormatException(IBaseCodec.EncodingFormatException); + } + + /// + /// Decodes the specified Base-64 representation into a . + /// + /// The Base-64 value to decode into a . + /// The format provider that will be used to decode the specified value. + /// Returns a new decoded from the specified value. + public byte[] Decode(ReadOnlySpan value, IFormatProvider? provider = null) + { + if (TryDecode(value, provider, out byte[] result)) return result; + throw new FormatException(IBaseCodec.DecodingFormatException); + } + + /// + /// Tries to encode the specified value into a Base-64 representation. + /// + /// The value to encode into a Base-64 representation. + /// The format provider that will be used to encode the specified value. + /// + /// A new Base-64 representation encoded from the specified value, + /// or an empty string if the specified value could not be encoded. + /// + /// Returns if the specified value was encoded successfully; otherwise, . + public bool TryEncode(ReadOnlySpan value, IFormatProvider? provider, out string result) + { + try + { + result = Convert.ToBase64String(value); + return true; + } + catch + { + result = string.Empty; + return false; + } + } + + /// + /// Tries to decode the specified Base-64 representation into a . + /// + /// The Base-64 value to decode into a . + /// The format provider that will be used to decode the specified value. + /// + /// A new decoded from the specified value, + /// or an empty if the specified value could not be decoded. + /// + /// Returns if the specified value was decoded successfully; otherwise, . + public bool TryDecode(ReadOnlySpan value, IFormatProvider? provider, out byte[] result) + { + try + { + result = Convert.FromBase64String(value.ToString()); + return true; + } + catch + { + result = []; + return false; + } + } +} diff --git a/OnixLabs.Core/Text/StringBuilderExtensions.cs b/OnixLabs.Core/Text/Extensions.StringBuilder.cs similarity index 99% rename from OnixLabs.Core/Text/StringBuilderExtensions.cs rename to OnixLabs.Core/Text/Extensions.StringBuilder.cs index e644d05..0131c9a 100644 --- a/OnixLabs.Core/Text/StringBuilderExtensions.cs +++ b/OnixLabs.Core/Text/Extensions.StringBuilder.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core/Text/IBaseCodec.cs b/OnixLabs.Core/Text/IBaseCodec.cs new file mode 100644 index 0000000..8b487f7 --- /dev/null +++ b/OnixLabs.Core/Text/IBaseCodec.cs @@ -0,0 +1,93 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +/// +/// Defines a codec for encoding and decoding Base-N values. +/// +public interface IBaseCodec +{ + /// + /// The exception message to throw for encoding operations. + /// + protected const string EncodingFormatException = "The specified value was not in the correct format and could not be encoded."; + + /// + /// The exception message to throw for decoding operations. + /// + protected const string DecodingFormatException = "The specified value was not in the correct format and could not be decoded."; + + /// + /// Gets a new instance. + /// + public static Base16Codec Base16 => new(); + + /// + /// Gets a new instance. + /// + public static Base32Codec Base32 => new(); + + /// + /// Gets a new instance. + /// + public static Base58Codec Base58 => new(); + + /// + /// Gets a new instance. + /// + public static Base64Codec Base64 => new(); + + /// + /// Encodes the specified value into a Base-N representation. + /// + /// The value to encode into a Base-N representation. + /// The format provider that will be used to encode the specified value. + /// Returns a new Base-N representation encoded from the specified value. + string Encode(ReadOnlySpan value, IFormatProvider? provider = null); + + /// + /// Decodes the specified Base-N representation into a . + /// + /// The Base-N value to decode into a . + /// The format provider that will be used to decode the specified value. + /// Returns a new decoded from the specified value. + byte[] Decode(ReadOnlySpan value, IFormatProvider? provider = null); + + /// + /// Tries to encode the specified value into a Base-N representation. + /// + /// The value to encode into a Base-N representation. + /// The format provider that will be used to encode the specified value. + /// + /// A new Base-N representation encoded from the specified value, + /// or an empty string if the specified value could not be encoded. + /// + /// Returns if the specified value was encoded successfully; otherwise, . + bool TryEncode(ReadOnlySpan value, IFormatProvider? provider, out string result); + + /// + /// Tries to decode the specified Base-N representation into a . + /// + /// The Base-N value to decode into a . + /// The format provider that will be used to decode the specified value. + /// + /// A new decoded from the specified value, + /// or an empty if the specified value could not be decoded. + /// + /// Returns if the specified value was decoded successfully; otherwise, . + bool TryDecode(ReadOnlySpan value, IFormatProvider? provider, out byte[] result); +} diff --git a/OnixLabs.Core/Text/IBaseRepresentation.cs b/OnixLabs.Core/Text/IBaseRepresentation.cs deleted file mode 100644 index 4094554..0000000 --- a/OnixLabs.Core/Text/IBaseRepresentation.cs +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Text; - -namespace OnixLabs.Core.Text; - -/// -/// Defines a number base representation. -/// -/// The underlying type of the number base representation. -public interface IBaseRepresentation : - IEquatable, - ISpanParsable, - ISpanFormattable - where TSelf : struct, IBaseRepresentation -{ - /// - /// Gets an empty value. - /// - public static abstract TSelf Empty { get; } - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(byte[] value); - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(ReadOnlySpan value); - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(string value); - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(string value, Encoding encoding); - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(char[] value); - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(char[] value, Encoding encoding); - - /// - /// Creates a new value from the specified value, using the default . - /// - /// The value from which to create a new value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(ReadOnlySpan value); - - /// - /// Creates a new value from the specified value. - /// - /// The value from which to create a new value. - /// The which will be used to obtain a from the specified value. - /// Returns a new value from the specified value. - public static abstract TSelf Create(ReadOnlySpan value, Encoding encoding); - - /// - /// Performs an equality check between two instances. - /// - /// The left-hand instance to compare. - /// The right-hand instance to compare. - /// Returns if the instances are equal; otherwise, . - public static abstract bool operator ==(TSelf left, TSelf right); - - /// - /// Performs an inequality check between two instances. - /// - /// The left-hand instance to compare. - /// The right-hand instance to compare. - /// Returns if the instances are not equal; otherwise, . - public static abstract bool operator !=(TSelf left, TSelf right); - - /// - /// Gets the underlying represented by the current value. - /// - /// Returns the underlying represented by the current value. - public byte[] ToByteArray(); - - /// - /// Gets the plain-text representation of the current value, using the default . - /// - /// Returns the plain-text representation of the current value, using the default . - public string ToPlainTextString(); - - /// - /// Gets the plain-text representation of the current value. - /// - /// The which will be used to obtain a from the current value. - /// Returns the plain-text representation of the current value. - public string ToPlainTextString(Encoding encoding); - - /// - /// Formats the value of the current instance using the specified format. - /// - /// The format to use. - /// The provider to use to format the value. - /// The value of the current instance in the specified format. - public string ToString(ReadOnlySpan format, IFormatProvider? formatProvider); -} diff --git a/OnixLabs.Core/Text/IBaseValue.cs b/OnixLabs.Core/Text/IBaseValue.cs new file mode 100644 index 0000000..103c244 --- /dev/null +++ b/OnixLabs.Core/Text/IBaseValue.cs @@ -0,0 +1,43 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; + +namespace OnixLabs.Core.Text; + +/// +/// Defines a Base-N value. +/// +public interface IBaseValue : IBinaryConvertible, ISpanFormattable +{ + /// + /// Formats the value of the current instance using the specified format. + /// + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + string ToString(IFormatProvider? formatProvider); + + /// + /// Formats the value of the current instance using the specified format. + /// + /// The format to use. + /// The provider to use to format the value. + /// The value of the current instance in the specified format. + string ToString(ReadOnlySpan format, IFormatProvider? formatProvider); +} + +/// +/// Defines a generic base encoding representation. +/// +public interface IBaseValue : IValueEquatable, ISpanParsable, IBaseValue where T : struct, IBaseValue; diff --git a/OnixLabs.Numerics.UnitTests.Data/OnixLabs.Numerics.UnitTests.Data.csproj b/OnixLabs.Numerics.UnitTests.Data/OnixLabs.Numerics.UnitTests.Data.csproj index fd8fb90..0d248c8 100644 --- a/OnixLabs.Numerics.UnitTests.Data/OnixLabs.Numerics.UnitTests.Data.csproj +++ b/OnixLabs.Numerics.UnitTests.Data/OnixLabs.Numerics.UnitTests.Data.csproj @@ -1,5 +1,4 @@ - net8.0 enable @@ -8,10 +7,9 @@ false true - - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -21,9 +19,10 @@ all - - + + + + - diff --git a/OnixLabs.Numerics.UnitTests/OnixLabs.Numerics.UnitTests.csproj b/OnixLabs.Numerics.UnitTests/OnixLabs.Numerics.UnitTests.csproj index 68667c4..dfe9b76 100644 --- a/OnixLabs.Numerics.UnitTests/OnixLabs.Numerics.UnitTests.csproj +++ b/OnixLabs.Numerics.UnitTests/OnixLabs.Numerics.UnitTests.csproj @@ -1,5 +1,4 @@ - net8.0 enable @@ -8,10 +7,9 @@ false true - - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -21,10 +19,11 @@ all - - - + + + + + - diff --git a/OnixLabs.Numerics/BigDecimal.Comparable.MinMax.cs b/OnixLabs.Numerics/BigDecimal.Comparable.MinMax.cs index 7b8d874..b9c9238 100644 --- a/OnixLabs.Numerics/BigDecimal.Comparable.MinMax.cs +++ b/OnixLabs.Numerics/BigDecimal.Comparable.MinMax.cs @@ -132,8 +132,6 @@ public static (int Min, int Max) MinMaxScale(BigDecimal left, BigDecimal right) return (min, max); } - - /// /// Gets the lesser of the specified values. /// diff --git a/OnixLabs.Numerics/BigDecimal.Convert.cs b/OnixLabs.Numerics/BigDecimal.Convert.cs index fd9c35f..88b5046 100644 --- a/OnixLabs.Numerics/BigDecimal.Convert.cs +++ b/OnixLabs.Numerics/BigDecimal.Convert.cs @@ -15,7 +15,6 @@ using System; using System.Diagnostics.CodeAnalysis; using System.Numerics; -using System.Runtime.CompilerServices; namespace OnixLabs.Numerics; diff --git a/OnixLabs.Numerics/BigDecimal.Convertible.Explicit.cs b/OnixLabs.Numerics/BigDecimal.Convertible.Explicit.cs index 1e04241..8ff95cd 100644 --- a/OnixLabs.Numerics/BigDecimal.Convertible.Explicit.cs +++ b/OnixLabs.Numerics/BigDecimal.Convertible.Explicit.cs @@ -147,9 +147,7 @@ public static explicit operator UInt128(BigDecimal value) public static explicit operator float(BigDecimal value) { if (value < float.MinValue || value > float.MaxValue) - { throw new OverflowException($"Value was either too large or too small for the specified type: {nameof(Single)}."); - } return Convert.ToSingle(value.ToString("E")); } @@ -162,9 +160,7 @@ public static explicit operator float(BigDecimal value) public static explicit operator double(BigDecimal value) { if (value < double.MinValue || value > double.MaxValue) - { throw new OverflowException($"Value was either too large or too small for the specified type: {nameof(Double)}."); - } return Convert.ToDouble(value.ToString("E")); } @@ -177,9 +173,7 @@ public static explicit operator double(BigDecimal value) public static explicit operator decimal(BigDecimal value) { if (value < decimal.MinValue || value > decimal.MaxValue) - { throw new OverflowException($"Value was either too large or too small for the specified type: {nameof(Decimal)}."); - } return Convert.ToDecimal(value.ToString("E")); } @@ -200,8 +194,6 @@ private static void CheckIntegerOverflow(BigDecimal value, T min, T max) wher BigInteger checkedMax = BigInteger.CreateChecked(max); if (value.number.Integer < checkedMin || value.number.Integer > checkedMax) - { throw new OverflowException($"Value was either too large or too small for the specified type: {typeof(T).Name}."); - } } } diff --git a/OnixLabs.Numerics/BigDecimal.Convertible.cs b/OnixLabs.Numerics/BigDecimal.Convertible.cs index 1e6408c..c7bef84 100644 --- a/OnixLabs.Numerics/BigDecimal.Convertible.cs +++ b/OnixLabs.Numerics/BigDecimal.Convertible.cs @@ -144,8 +144,7 @@ decimal IConvertible.ToDecimal(IFormatProvider? provider) /// Returns a instance equivalent to the value of this instance. DateTime IConvertible.ToDateTime(IFormatProvider? provider) { - long binary = (long)UnscaledValue; - return DateTime.FromBinary(binary); + return DateTime.FromBinary((long)UnscaledValue); } /// diff --git a/OnixLabs.Numerics/BigDecimal.Equatable.cs b/OnixLabs.Numerics/BigDecimal.Equatable.cs index 094196c..72ec86c 100644 --- a/OnixLabs.Numerics/BigDecimal.Equatable.cs +++ b/OnixLabs.Numerics/BigDecimal.Equatable.cs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; - namespace OnixLabs.Numerics; public readonly partial struct BigDecimal diff --git a/OnixLabs.Numerics/BigDecimal.cs b/OnixLabs.Numerics/BigDecimal.cs index f6b697e..2de9c4d 100644 --- a/OnixLabs.Numerics/BigDecimal.cs +++ b/OnixLabs.Numerics/BigDecimal.cs @@ -14,13 +14,14 @@ using System; using System.Numerics; +using OnixLabs.Core; namespace OnixLabs.Numerics; /// /// Represents an arbitrarily large signed decimal. /// -public readonly partial struct BigDecimal : IFloatingPoint, IConvertible +public readonly partial struct BigDecimal : IFloatingPoint, IValueEquatable, IValueComparable, IConvertible { /// /// The underlying that represents the current value. diff --git a/OnixLabs.Numerics/NumberInfo.cs b/OnixLabs.Numerics/NumberInfo.cs index 2002e39..5a47e61 100644 --- a/OnixLabs.Numerics/NumberInfo.cs +++ b/OnixLabs.Numerics/NumberInfo.cs @@ -14,6 +14,7 @@ using System; using System.Numerics; +using OnixLabs.Core; namespace OnixLabs.Numerics; @@ -21,10 +22,8 @@ namespace OnixLabs.Numerics; /// Represents component information about rational numbers. /// public readonly partial struct NumberInfo : - IEquatable, - IComparable, - IComparable, - IComparisonOperators, + IValueEquatable, + IValueComparable, ISpanParsable, IFormattable { diff --git a/OnixLabs.Numerics/NumberInfoParser.cs b/OnixLabs.Numerics/NumberInfoParser.cs index 54a8094..1da1248 100644 --- a/OnixLabs.Numerics/NumberInfoParser.cs +++ b/OnixLabs.Numerics/NumberInfoParser.cs @@ -50,7 +50,7 @@ public bool TryParse(ReadOnlySpan value, out NumberInfo result) if (!TrySanitizeNumber(ref value, out sign, out exponent)) return false; } - // At this point, only digits, thousand and decimal separators should remain. + // At this point, only digits, thousands and decimal separators should remain. if (!TryGetNumberInfo(ref value, out NumberInfo rawResult)) return false; result = new NumberInfo(rawResult.UnscaledValue * sign, int.Max(rawResult.Scale - exponent, 0)); diff --git a/OnixLabs.Numerics/OnixLabs.Numerics.csproj b/OnixLabs.Numerics/OnixLabs.Numerics.csproj index 580f0fc..9a4ac05 100644 --- a/OnixLabs.Numerics/OnixLabs.Numerics.csproj +++ b/OnixLabs.Numerics/OnixLabs.Numerics.csproj @@ -8,7 +8,7 @@ en enable true - Copyright © ONIXLabs 2020-2023 + Copyright © ONIXLabs 2020 https://github.com/onix-labs/onixlabs-dotnet 6.0.0 12 @@ -44,6 +44,5 @@ - diff --git a/OnixLabs.Playground/OnixLabs.Playground.csproj b/OnixLabs.Playground/OnixLabs.Playground.csproj index 7da8371..61923dc 100644 --- a/OnixLabs.Playground/OnixLabs.Playground.csproj +++ b/OnixLabs.Playground/OnixLabs.Playground.csproj @@ -7,15 +7,14 @@ true - false + false - + - diff --git a/OnixLabs.Playground/Program.cs b/OnixLabs.Playground/Program.cs index 1045f54..d629839 100644 --- a/OnixLabs.Playground/Program.cs +++ b/OnixLabs.Playground/Program.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/OnixLabs.Core.UnitTests.Data/Objects/Element.cs b/OnixLabs.Security.Cryptography.UnitTests.Data/MerkleNode.cs similarity index 62% rename from OnixLabs.Core.UnitTests.Data/Objects/Element.cs rename to OnixLabs.Security.Cryptography.UnitTests.Data/MerkleNode.cs index 640b6c9..43e0b6a 100644 --- a/OnixLabs.Core.UnitTests.Data/Objects/Element.cs +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/MerkleNode.cs @@ -1,31 +1,25 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -namespace OnixLabs.Core.UnitTests.Data.Objects; +using System.Security.Cryptography; -public sealed class Element -{ - public Element(int hashCode = 0) - { - HashCode = hashCode; - } +namespace OnixLabs.Security.Cryptography.UnitTests.Data; - public bool Called { get; set; } - private int HashCode { get; } - - public override int GetHashCode() +public sealed record MerkleNode(string Text, int Number, DateTime Moment, Guid Identifier) : IHashable +{ + public Hash ComputeHash(HashAlgorithm algorithm) { - return HashCode; + return Hash.Compute(algorithm, ToString()); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs b/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs deleted file mode 100644 index 00f6ecd..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests.Data/Objects/MerkleNode.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core; - -namespace OnixLabs.Security.Cryptography.UnitTests.Data.Objects; - -public sealed class MerkleNode : IEquatable, IHashable -{ - public MerkleNode(string text, int number, DateTime moment, Guid identifier) - { - Text = text; - Number = number; - Moment = moment; - Identifier = identifier; - } - - public string Text { get; } - public int Number { get; } - public DateTime Moment { get; } - public Guid Identifier { get; } - - public Hash ComputeHash() - { - return Hash.ComputeSha2Hash256(ToString()); - } - - public bool Equals(MerkleNode? other) - { - return ReferenceEquals(this, other) - || other is not null - && other.Text == Text - && other.Number == Number - && other.Moment == Moment - && other.Identifier == Identifier; - } - - public override bool Equals(object? obj) - { - return Equals(obj as MerkleNode); - } - - public override int GetHashCode() - { - return HashCode.Combine(Text, Number, Moment, Identifier); - } - - public override string ToString() - { - return this.ToRecordString(); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj b/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj index e2195ca..c69cd04 100644 --- a/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/OnixLabs.Security.Cryptography.UnitTests.Data.csproj @@ -1,5 +1,4 @@ - net8.0 enable @@ -9,10 +8,9 @@ 12 - - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -22,13 +20,10 @@ all - - + - - + - diff --git a/OnixLabs.Core/Text/Base64.Constants.cs b/OnixLabs.Security.Cryptography.UnitTests.Data/TestPrivateKey.cs similarity index 56% rename from OnixLabs.Core/Text/Base64.Constants.cs rename to OnixLabs.Security.Cryptography.UnitTests.Data/TestPrivateKey.cs index bd35494..d9f0270 100644 --- a/OnixLabs.Core/Text/Base64.Constants.cs +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/TestPrivateKey.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,15 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; -using System.Text; +using System.Security.Cryptography; -namespace OnixLabs.Core.Text; +namespace OnixLabs.Security.Cryptography.UnitTests.Data; -public readonly partial struct Base64 +public sealed class TestPrivateKey(ReadOnlySpan value) : PrivateKey(value) { - /// - /// Gets an empty value. - /// - public static Base64 Empty => new([]); + public override PublicKey GetPublicKey() => new TestPublicKey([]); + public override byte[] ExportPkcs8PrivateKey() => []; + public override byte[] ExportPkcs8PrivateKey(ReadOnlySpan password, PbeParameters parameters) => []; } diff --git a/OnixLabs.Security.Cryptography/Hash.Constants.cs b/OnixLabs.Security.Cryptography.UnitTests.Data/TestPublicKey.cs similarity index 68% rename from OnixLabs.Security.Cryptography/Hash.Constants.cs rename to OnixLabs.Security.Cryptography.UnitTests.Data/TestPublicKey.cs index df27540..2e4390e 100644 --- a/OnixLabs.Security.Cryptography/Hash.Constants.cs +++ b/OnixLabs.Security.Cryptography.UnitTests.Data/TestPublicKey.cs @@ -1,23 +1,17 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -namespace OnixLabs.Security.Cryptography; +namespace OnixLabs.Security.Cryptography.UnitTests.Data; -public readonly partial struct Hash -{ - /// - /// Gets an empty hash value. - /// - public static Hash Empty => Create(EmptyArray()); -} +public sealed class TestPublicKey(ReadOnlySpan value) : PublicKey(value); diff --git a/OnixLabs.Security.Cryptography.UnitTests/DigitalSignatureTests.cs b/OnixLabs.Security.Cryptography.UnitTests/DigitalSignatureTests.cs new file mode 100644 index 0000000..497453f --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests/DigitalSignatureTests.cs @@ -0,0 +1,123 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Xunit; + +namespace OnixLabs.Security.Cryptography.UnitTests; + +public sealed class DigitalSignatureTests +{ + [Fact(DisplayName = "DigitalSignature should be constructable from bytes")] + public void DigitalSignatureShouldBeConstructableFromBytes() + { + // Given + byte[] value = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + const string expected = "000102030405060708090a0b0c0d0e0f"; + + // When + DigitalSignature candidate = new(value); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "DigitalSignature value should not be modified when altering the original byte array")] + public void DigitalSignatureValueShouldNotBeModifiedWhenAlteringTheOriginalByteArray() + { + // Given + byte[] value = [1, 2, 3, 4]; + DigitalSignature candidate = new(value); + const string expected = "01020304"; + + // When + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "DigitalSignature value should not be modified when altering the obtained byte array")] + public void DigitalSignatureValueShouldNotBeModifiedWhenAlteringTheObtainedByteArray() + { + // Given + DigitalSignature candidate = new([1, 2, 3, 4]); + const string expected = "01020304"; + + // When + byte[] value = candidate.ToByteArray(); + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Identical signature values should be considered equal")] + public void IdenticalDigitalSignatureValuesShouldBeConsideredEqual() + { + // Given + DigitalSignature left = new([1, 2, 3, 4]); + DigitalSignature right = new([1, 2, 3, 4]); + + // Then + Assert.Equal(left, right); + Assert.True(left.Equals(right)); + Assert.True(left == right); + } + + [Fact(DisplayName = "Different signature values should not be considered equal")] + public void DifferentDigitalSignatureValuesShouldNotBeConsideredEqual() + { + // Given + DigitalSignature left = new([1, 2, 3, 4]); + DigitalSignature right = new([5, 6, 7, 8]); + + // Then + Assert.NotEqual(left, right); + Assert.False(left.Equals(right)); + Assert.True(left != right); + } + + [Fact(DisplayName = "Identical signature values should produce identical hash codes")] + public void IdenticalDigitalSignatureValuesShouldProduceIdenticalDigitalSignatureCodes() + { + // Given + DigitalSignature left = new([1, 2, 3, 4]); + DigitalSignature right = new([1, 2, 3, 4]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.Equal(leftHashCode, rightHashCode); + } + + [Fact(DisplayName = "Different signature values should produce different hash codes")] + public void DifferentDigitalSignatureValuesShouldProduceDifferentDigitalSignatureCodes() + { + // Given + DigitalSignature left = new([1, 2, 3, 4]); + DigitalSignature right = new([5, 6, 7, 8]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.NotEqual(leftHashCode, rightHashCode); + } +} diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs deleted file mode 100644 index 6e218c7..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaEncryptedPkcs8Tests.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Collections.Generic; -using System.Security.Cryptography; -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class EcdsaKeyEncryptedPkcs8Tests : KeyTestBase -{ - [Fact(DisplayName = "Two identical ECDSA PKCS #8 private keys should be considered equal")] - public void TwoIdenticalPrivateKeysShouldBeConsideredEqual() - { - // Arrange - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - const string password = "This is a secret!"; - PbeParameters parameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 64); - - // Act - byte[] pkcs8PrivateKey = privateKey1.ExportPkcs8Key(password, parameters); - PrivateKey privateKey2 = EcdsaPrivateKey.ImportPkcs8Key(pkcs8PrivateKey, password, type); - - // Assert - Assert.Equal(privateKey1, privateKey2); - } - - [Fact(DisplayName = "Two identical ECDSA PKCS #8 keys should be able to sign and verify the same data")] - public void TwoIdenticalEcdsaKeysShouldBeAbleToSignAndVerifyTheSameData() - { - // Arrange - IList<(DigitalSignature, byte[])> signatures = new List<(DigitalSignature, byte[])>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - const string password = "This is a secret!"; - PbeParameters parameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 64); - byte[] pkcs8PrivateKey = privateKey1.ExportPkcs8Key(password, parameters); - PrivateKey privateKey2 = EcdsaPrivateKey.ImportPkcs8Key(pkcs8PrivateKey, password, type); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - DigitalSignature signature1 = privateKey1.SignData(data); - DigitalSignature signature2 = privateKey2.SignData(data); - - signatures.Add((signature1, data)); - signatures.Add((signature2, data)); - } - - // Assert - foreach ((DigitalSignature signature, byte[] data) in signatures) - { - Assert.True(signature.IsDataValid(data, publicKey1)); - Assert.True(signature.IsDataValid(data, publicKey2)); - } - } - - [Fact(DisplayName = "Two identical ECDSA PKCS #8 keys should be able to sign and verify the same hash")] - public void TwoIdenticalEcdsaKeysShouldBeAbleToSignAndVerifyTheSameHash() - { - // Arrange - IList<(DigitalSignature, Hash)> signatures = new List<(DigitalSignature, Hash)>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - const string password = "This is a secret!"; - PbeParameters parameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 64); - byte[] pkcs8PrivateKey = privateKey1.ExportPkcs8Key(password, parameters); - PrivateKey privateKey2 = EcdsaPrivateKey.ImportPkcs8Key(pkcs8PrivateKey, password, type); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - Hash hashedData = Hash.ComputeSha2Hash256(data); - DigitalSignature signature1 = privateKey1.SignHash(hashedData); - DigitalSignature signature2 = privateKey2.SignHash(hashedData); - - signatures.Add((signature1, hashedData)); - signatures.Add((signature2, hashedData)); - } - - // Assert - foreach ((DigitalSignature signature, Hash hashedData) in signatures) - { - Assert.True(signature.IsHashValid(hashedData, publicKey1)); - Assert.True(signature.IsHashValid(hashedData, publicKey2)); - } - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs deleted file mode 100644 index 89b91b5..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyPkcs8Tests.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Collections.Generic; -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class EcdsaKeyPkcs8Tests : KeyTestBase -{ - [Fact(DisplayName = "Two identical ECDSA PKCS #8 private keys should be considered equal")] - public void TwoIdenticalPrivateKeysShouldBeConsideredEqual() - { - // Arrange - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - - // Act - byte[] pkcs8PrivateKey = privateKey1.ExportPkcs8Key(); - PrivateKey privateKey2 = EcdsaPrivateKey.ImportPkcs8Key(pkcs8PrivateKey, type); - - // Assert - Assert.Equal(privateKey1, privateKey2); - } - - [Fact(DisplayName = "Two identical ECDSA PKCS #8 keys should be able to sign and verify the same data")] - public void TwoIdenticalEcdsaKeysShouldBeAbleToSignAndVerifyTheSameData() - { - // Arrange - IList<(DigitalSignature, byte[])> signatures = new List<(DigitalSignature, byte[])>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = EcdsaPrivateKey.ImportPkcs8Key(privateKey1.ExportPkcs8Key(), type); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - DigitalSignature signature1 = privateKey1.SignData(data); - DigitalSignature signature2 = privateKey2.SignData(data); - - signatures.Add((signature1, data)); - signatures.Add((signature2, data)); - } - - // Assert - foreach ((DigitalSignature signature, byte[] data) in signatures) - { - Assert.True(signature.IsDataValid(data, publicKey1)); - Assert.True(signature.IsDataValid(data, publicKey2)); - } - } - - [Fact(DisplayName = "Two identical ECDSA PKCS #8 keys should be able to sign and verify the same hash")] - public void TwoIdenticalEcdsaKeysShouldBeAbleToSignAndVerifyTheSameHash() - { - // Arrange - IList<(DigitalSignature, Hash)> signatures = new List<(DigitalSignature, Hash)>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = EcdsaPrivateKey.ImportPkcs8Key(privateKey1.ExportPkcs8Key(), type); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - Hash hashedData = Hash.ComputeSha2Hash256(data); - DigitalSignature signature1 = privateKey1.SignHash(hashedData); - DigitalSignature signature2 = privateKey2.SignHash(hashedData); - - signatures.Add((signature1, hashedData)); - signatures.Add((signature2, hashedData)); - } - - // Assert - foreach ((DigitalSignature signature, Hash hashedData) in signatures) - { - Assert.True(signature.IsHashValid(hashedData, publicKey1)); - Assert.True(signature.IsHashValid(hashedData, publicKey2)); - } - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs index 07f7098..45ff4f8 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/EcdsaKeyTests.cs @@ -1,117 +1,43 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using System.Collections.Generic; -using OnixLabs.Core.Text; +using System.Security.Cryptography; using Xunit; namespace OnixLabs.Security.Cryptography.UnitTests; -public sealed class EcdsaKeyTests : KeyTestBase +public sealed class EcdsaKeyTests { - [Fact(DisplayName = "Two identical ECDSA private keys should be considered equal")] - public void TwoIdenticalPrivateKeysShouldBeConsideredEqual() + [Fact(DisplayName = "ECDSA sign and verify with two identical keys should succeed")] + public void EcdsaSignAndVerifyWithTwoIdenticalKeysShouldSucceed() { - // Arrange - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - - // Act - Base58 base58PrivateKey = privateKey1.ToBase58(); - PrivateKey privateKey2 = EcdsaPrivateKey.Create(base58PrivateKey, type); - - // Assert - Assert.Equal(privateKey1, privateKey2); - } - - [Fact(DisplayName = "Two identical ECDSA public keys should be considered equal")] - public void TwoIdenticalPublicKeysShouldBeConsideredEqual() - { - // Arrange - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PublicKey publicKey1 = pair.PublicKey; - - // Act - Base58 base58PublicKey = publicKey1.ToBase58(); - PublicKey publicKey2 = EcdsaPublicKey.Create(base58PublicKey, type); - - // Assert - Assert.Equal(publicKey1, publicKey2); - } - - [Fact(DisplayName = "Two identical ECDSA keys should be able to sign and verify the same data")] - public void TwoIdenticalEcdsaKeysShouldBeAbleToSignAndVerifyTheSameData() - { - // Arrange - IList<(DigitalSignature, byte[])> signatures = new List<(DigitalSignature, byte[])>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = EcdsaPrivateKey.Create(privateKey1.ToBase64(), type); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - DigitalSignature signature1 = privateKey1.SignData(data); - DigitalSignature signature2 = privateKey2.SignData(data); - - signatures.Add((signature1, data)); - signatures.Add((signature2, data)); - } - - // Assert - foreach ((DigitalSignature signature, byte[] data) in signatures) - { - Assert.True(signature.IsDataValid(data, publicKey1)); - Assert.True(signature.IsDataValid(data, publicKey2)); - } - } - - [Fact(DisplayName = "Two identical ECDSA keys should be able to sign and verify the same hash")] - public void TwoIdenticalEcdsaKeysShouldBeAbleToSignAndVerifyTheSameHash() - { - // Arrange - IList<(DigitalSignature, Hash)> signatures = new List<(DigitalSignature, Hash)>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - KeyPair pair = KeyPair.CreateEcdsaKeyPair(type); - PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = EcdsaPrivateKey.Create(privateKey1.ToBase64(), type); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - Hash hashedData = Hash.ComputeSha2Hash256(data); - DigitalSignature signature1 = privateKey1.SignHash(hashedData); - DigitalSignature signature2 = privateKey2.SignHash(hashedData); - - signatures.Add((signature1, hashedData)); - signatures.Add((signature2, hashedData)); - } - - // Assert - foreach ((DigitalSignature signature, Hash hashedData) in signatures) - { - Assert.True(signature.IsHashValid(hashedData, publicKey1)); - Assert.True(signature.IsHashValid(hashedData, publicKey2)); - } + // Given + byte[] data = Salt.CreateNonZero(2048).ToByteArray(); + HashAlgorithm algorithm = SHA256.Create(); + IEcdsaPrivateKey privateKey1 = EcdsaPrivateKey.Create(); + IEcdsaPrivateKey privateKey2 = new EcdsaPrivateKey(privateKey1.ToByteArray()); + IEcdsaPublicKey publicKey1 = privateKey1.GetPublicKey(); + IEcdsaPublicKey publicKey2 = privateKey2.GetPublicKey(); + + // When + DigitalSignature signature1 = new(privateKey1.SignData(data, algorithm)); + DigitalSignature signature2 = new(privateKey2.SignData(data, algorithm)); + + // Then + Assert.True(publicKey1.IsDataValid(signature1, data, algorithm)); + Assert.True(publicKey1.IsDataValid(signature2, data, algorithm)); + Assert.True(publicKey2.IsDataValid(signature1, data, algorithm)); + Assert.True(publicKey2.IsDataValid(signature2, data, algorithm)); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashAlgorithmExtensionTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashAlgorithmExtensionTests.cs new file mode 100644 index 0000000..e172a98 --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests/HashAlgorithmExtensionTests.cs @@ -0,0 +1,55 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using Xunit; + +namespace OnixLabs.Security.Cryptography.UnitTests; + +public sealed class HashAlgorithmExtensionTests +{ + [Fact(DisplayName = "HashAlgorithm.ComputeHash should produce the expected result with two rounds")] + public void HashAlgorithmComputeHashShouldProduceExpectedResultWithTwoRounds() + { + // Given + using HashAlgorithm algorithm = SHA256.Create(); + const string expected = "efaaeb3b1d1d85e8587ef0527ca43b9575ce8149ba1ee41583d3d19bd130daf8"; + + // When + byte[] bytes = algorithm.ComputeHash("abc123", rounds: 2); + string actual = Convert.ToHexString(bytes).ToLower(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "HashAlgorithm.ComputeHashAsync should produce the expected result with two rounds")] + public async void HashAlgorithmComputeHashAsyncShouldProduceExpectedResultWithTwoRounds() + { + // Given + using HashAlgorithm algorithm = SHA256.Create(); + Stream data = new MemoryStream(Encoding.Default.GetBytes("abc123")); + const string expected = "efaaeb3b1d1d85e8587ef0527ca43b9575ce8149ba1ee41583d3d19bd130daf8"; + + // When + byte[] bytes = await algorithm.ComputeHashAsync(data, 2); + string actual = Convert.ToHexString(bytes).ToLower(); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs deleted file mode 100644 index c06e6ff..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/HashAsyncTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class HashAsyncTests -{ - [Fact(DisplayName = "Identical hashes should be considered equal")] - public async void IdenticalHashesShouldBeConsideredEqual() - { - // Arrange - Hash a = await Hash.ComputeSha2Hash256Async("abcdefghijklmnopqrstuvwxyz"); - Hash b = await Hash.ComputeSha2Hash256Async("abcdefghijklmnopqrstuvwxyz"); - - // Assert - Assert.Equal(a, b); - } - - [Fact(DisplayName = "Different hashes should not be considered equal")] - public async void DifferentHashesShouldNotBeConsideredEqual() - { - // Arrange - Hash a = await Hash.ComputeSha2Hash256Async("abcdefghijklmnopqrstuvwxyz"); - Hash b = await Hash.ComputeSha2Hash256Async("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - - // Assert - Assert.NotEqual(a, b); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs index df5e492..58dc039 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/HashTests.cs @@ -1,132 +1,429 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core.Collections; +using System; +using System.IO; +using System.Security.Cryptography; +using OnixLabs.Core; using Xunit; namespace OnixLabs.Security.Cryptography.UnitTests; public sealed class HashTests { - [Fact(DisplayName = "Identical Hash values produce identical hash codes.")] - public void IdenticalHashValuesProduceIdenticalHashCodes() + [Fact(DisplayName = "Hash should be constructable from bytes")] + public void HashShouldBeConstructableFromBytes() { - // Arrange - Hash a = Hash.ComputeSha2Hash256("abcdefghijklmnopqrstuvwxyz"); - Hash b = Hash.ComputeSha2Hash256("abcdefghijklmnopqrstuvwxyz"); + // Given + byte[] value = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + const string expected = "000102030405060708090a0b0c0d0e0f"; - // Act - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); + // When + Hash candidate = new(value); + string actual = candidate.ToString(); - // Assert - Assert.Equal(hashCodeA, hashCodeB); + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Hash should be constructable from byte and length")] + public void HashShouldBeConstructableFromByteAndLength() + { + // Given + const byte value = 0xF0; + const int length = 16; + const string expected = "f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0"; + + // When + Hash candidate = new(value, length); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Hash value should not be modified when altering the original byte array")] + public void HashValueShouldNotBeModifiedWhenAlteringTheOriginalByteArray() + { + // Given + byte[] value = [1, 2, 3, 4]; + Hash candidate = new(value); + const string expected = "01020304"; + + // When + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Hash value should not be modified when altering the obtained byte array")] + public void HashValueShouldNotBeModifiedWhenAlteringTheObtainedByteArray() + { + // Given + Hash candidate = new([1, 2, 3, 4]); + const string expected = "01020304"; + + // When + byte[] value = candidate.ToByteArray(); + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Identical hash values should be considered equal")] + public void IdenticalHashValuesShouldBeConsideredEqual() + { + // Given + Hash left = new([1, 2, 3, 4]); + Hash right = new([1, 2, 3, 4]); + + // Then + Assert.Equal(left, right); + Assert.True(left.Equals(right)); + Assert.True(left == right); + } + + [Fact(DisplayName = "Different hash values should not be considered equal")] + public void DifferentHashValuesShouldNotBeConsideredEqual() + { + // Given + Hash left = new([1, 2, 3, 4]); + Hash right = new([5, 6, 7, 8]); + + // Then + Assert.NotEqual(left, right); + Assert.False(left.Equals(right)); + Assert.True(left != right); } - [Fact(DisplayName = "Identical hashes should be considered equal")] - public void IdenticalHashesShouldBeConsideredEqual() + [Fact(DisplayName = "Identical hash values should produce identical hash codes")] + public void IdenticalHashValuesShouldProduceIdenticalHashCodes() { - // Arrange - Hash a = Hash.ComputeSha2Hash256("abcdefghijklmnopqrstuvwxyz"); - Hash b = Hash.ComputeSha2Hash256("abcdefghijklmnopqrstuvwxyz"); + // Given + Hash left = new([1, 2, 3, 4]); + Hash right = new([1, 2, 3, 4]); - // Assert - Assert.Equal(a, b); + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.Equal(leftHashCode, rightHashCode); } - [Fact(DisplayName = "Different hashes should not be considered equal")] - public void DifferentHashesShouldNotBeConsideredEqual() + [Fact(DisplayName = "Different hash values should produce different hash codes")] + public void DifferentHashValuesShouldProduceDifferentHashCodes() { - // Arrange - Hash a = Hash.ComputeSha2Hash256("abcdefghijklmnopqrstuvwxyz"); - Hash b = Hash.ComputeSha2Hash256("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + // Given + Hash left = new([1, 2, 3, 4]); + Hash right = new([5, 6, 7, 8]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); - // Assert - Assert.NotEqual(a, b); + // Then + Assert.NotEqual(leftHashCode, rightHashCode); } - [Fact(DisplayName = "Hashes should produce a negative-one sort order when the left-hand hash is less than the right-hand hash")] - public void HashesShouldProduceANegativeOneSortOrderWhenTheLeftHandHashIsLessThanTheRightHandHash() + [Fact(DisplayName = "Hashes should produce a negative-one sort order when the left-hand hash is lesser than the right-hand hash")] + public void HashesShouldProduceANegativeOneSortOrderWhenTheLeftHandHashIsLesserThanTheRightHandHash() { - // Arrange - Hash a = Hash.Create(ArrayOf(1)); - Hash b = Hash.Create(ArrayOf(2)); + // Given + Hash left = new([1]); + Hash right = new([2]); const int expected = -1; - // Act - int actual = a.CompareTo(b); + // When + int actual = left.CompareTo(right); - // Assert + // Then Assert.Equal(expected, actual); } [Fact(DisplayName = "Hashes should produce a positive-one sort order when the left-hand hash is greater than the right-hand hash")] public void HashesShouldProduceAPositiveOneSortOrderWhenTheLeftHandHashIsGreaterThanTheRightHandHash() { - // Arrange - Hash a = Hash.Create(ArrayOf(2)); - Hash b = Hash.Create(ArrayOf(1)); + // Given + Hash left = new([2]); + Hash right = new([1]); const int expected = 1; - // Act - int actual = a.CompareTo(b); + // When + int actual = left.CompareTo(right); - // Assert + // Then Assert.Equal(expected, actual); } [Fact(DisplayName = "Hashes should produce a zero sort order when the left-hand hash is equal to the right-hand hash")] public void HashesShouldProduceAZeroSortOrderWhenTheLeftHandHashIsEqualToTheRightHandHash() { - // Arrange - Hash a = Hash.Create(ArrayOf(1)); - Hash b = Hash.Create(ArrayOf(1)); + // Given + Hash left = new([1]); + Hash right = new([1]); const int expected = 0; - // Act - int actual = a.CompareTo(b); + // When + int actual = left.CompareTo(right); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Hash.Compute should produce the expected hash using a byte array")] + [InlineData("abc123", "MD5", "e99a18c428cb38d5f260853678922e03")] + [InlineData("abc123", "SHA1", "6367c48dd193d56ea7b0baad25b19455e529f5ee")] + [InlineData("abc123", "SHA256", "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090")] + [InlineData("abc123", "SHA384", "a31d79891919cad24f3264479d76884f581bee32e86778373db3a124de975dd86a40fc7f399b331133b281ab4b11a6ca")] + [InlineData("abc123", "SHA512", "c70b5dd9ebfb6f51d09d4132b7170c9d20750a7852f00680f65658f0310e810056e6763c34c9a00b0e940076f54495c169fc2302cceb312039271c43469507dc")] + public void HashComputeShouldProduceTheExpectedHashUsingAByteArray(string data, string algorithmName, string expected) + { + // Given + byte[] bytes = data.ToByteArray(); + HashAlgorithm algorithm = algorithmName switch + { + "MD5" => MD5.Create(), + "SHA1" => SHA1.Create(), + "SHA256" => SHA256.Create(), + "SHA384" => SHA384.Create(), + "SHA512" => SHA512.Create(), + _ => throw new ArgumentException($"Unknown hash algorithm name: {algorithmName}.") + }; + + // When + Hash candidate = Hash.Compute(algorithm, bytes); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Hash.Compute should produce the expected hash using a byte array with two rounds")] + [InlineData("abc123", "MD5", "b106dc6352e5ec1f8aafd8c406d34d92")] + [InlineData("abc123", "SHA1", "6691484ea6b50ddde1926a220da01fa9e575c18a")] + [InlineData("abc123", "SHA256", "efaaeb3b1d1d85e8587ef0527ca43b9575ce8149ba1ee41583d3d19bd130daf8")] + [InlineData("abc123", "SHA384", "d58e9a112b8c637df5d2e33af03ce738dd1c57657243d70d2fa8f76a99fa9a0e2f4abf50d9a88e8958f2d5f6fa002190")] + [InlineData("abc123", "SHA512", "c2c9d705d7a1ed34247649bbe64c6edd2035e0a4c9ae1c063170f5ee2aeca09125cc0a8b30593c07a18801d6e0570de22e8dc40a59bc1f59a49834c05ed49949")] + public void HashComputeShouldProduceTheExpectedHashUsingAByteArrayWithTwoRounds(string data, string algorithmName, string expected) + { + // Given + byte[] bytes = data.ToByteArray(); + HashAlgorithm algorithm = algorithmName switch + { + "MD5" => MD5.Create(), + "SHA1" => SHA1.Create(), + "SHA256" => SHA256.Create(), + "SHA384" => SHA384.Create(), + "SHA512" => SHA512.Create(), + _ => throw new ArgumentException($"Unknown hash algorithm name: {algorithmName}.") + }; + + // When + Hash candidate = Hash.Compute(algorithm, bytes, 2); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Hash.Compute should produce the expected hash using a byte array with an offset and count")] + [InlineData("abc123", 1, 3, "MD5", "b79f52be223290bd34f94e92aa8b0bdd")] + [InlineData("abc123", 1, 3, "SHA1", "be4a30dd01a93831a222262d9fa288c4f016b822")] + [InlineData("abc123", 1, 3, "SHA256", "fa54bf6e8e528001735fcc222c3ef5b99c46f469d9340deae3d9577818a6fe5a")] + [InlineData("abc123", 1, 3, "SHA384", "3cfd879e784ed23f3e9142775218bbaf636bd5413d32583a10f79f6b63028cbe9e241273dabe293c27876db2ecbaa594")] + [InlineData("abc123", 1, 3, "SHA512", "65f2fea7da1b1e470169d7f861000047ac78e00a024f5973322e5850d5fd61ceb94b7252629426bfa4beb3dafc9f55c747b5b2a8374f545e19148e61ef0057cc")] + public void HashComputeShouldProduceTheExpectedHashUsingAByteArrayWithAnOffsetAndCount(string data, int offset, int count, string algorithmName, string expected) + { + // Given + byte[] bytes = data.ToByteArray(); + HashAlgorithm algorithm = algorithmName switch + { + "MD5" => MD5.Create(), + "SHA1" => SHA1.Create(), + "SHA256" => SHA256.Create(), + "SHA384" => SHA384.Create(), + "SHA512" => SHA512.Create(), + _ => throw new ArgumentException($"Unknown hash algorithm name: {algorithmName}.") + }; + + // When + Hash candidate = Hash.Compute(algorithm, bytes, offset, count); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Hash.Compute should produce the expected hash using a byte array with an offset, count and two rounds")] + [InlineData("abc123", 1, 3, "MD5", "05787e59f464916f6dfdf5bf5996e152")] + [InlineData("abc123", 1, 3, "SHA1", "33dcbf41c6e49b12ad37b5dab4d95dcc6ee71f49")] + [InlineData("abc123", 1, 3, "SHA256", "5a9828edeba2a57521b2d40648cc69a4e0c236111dfae612075399ba588eee91")] + [InlineData("abc123", 1, 3, "SHA384", "5691be426e2e501f5598cfc0355fc7de2c1c15637daf98ee09bf7d1da75463bf33a96a2164facbd535515c54e5d56920")] + [InlineData("abc123", 1, 3, "SHA512", "74da074abe82913bc91a3079ac7d55b8bb1e111d10647b31d6c881a93427ebc57a6c4aeca5efba612e9b71c38e6601a13df0e7d73e1530ed65453c8926404186")] + public void HashComputeShouldProduceTheExpectedHashUsingAByteArrayWithAnOffsetCountAndTwoRounds(string data, int offset, int count, string algorithmName, string expected) + { + // Given + byte[] bytes = data.ToByteArray(); + HashAlgorithm algorithm = algorithmName switch + { + "MD5" => MD5.Create(), + "SHA1" => SHA1.Create(), + "SHA256" => SHA256.Create(), + "SHA384" => SHA384.Create(), + "SHA512" => SHA512.Create(), + _ => throw new ArgumentException($"Unknown hash algorithm name: {algorithmName}.") + }; + + // When + Hash candidate = Hash.Compute(algorithm, bytes, offset, count, 2); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Hash.Compute should produce the expected hash using a stream")] + [InlineData("abc123", "MD5", "e99a18c428cb38d5f260853678922e03")] + [InlineData("abc123", "SHA1", "6367c48dd193d56ea7b0baad25b19455e529f5ee")] + [InlineData("abc123", "SHA256", "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090")] + [InlineData("abc123", "SHA384", "a31d79891919cad24f3264479d76884f581bee32e86778373db3a124de975dd86a40fc7f399b331133b281ab4b11a6ca")] + [InlineData("abc123", "SHA512", "c70b5dd9ebfb6f51d09d4132b7170c9d20750a7852f00680f65658f0310e810056e6763c34c9a00b0e940076f54495c169fc2302cceb312039271c43469507dc")] + public void HashComputeShouldProduceTheExpectedHashUsingAStream(string data, string algorithmName, string expected) + { + // Given + Stream stream = new MemoryStream(data.ToByteArray()); + HashAlgorithm algorithm = algorithmName switch + { + "MD5" => MD5.Create(), + "SHA1" => SHA1.Create(), + "SHA256" => SHA256.Create(), + "SHA384" => SHA384.Create(), + "SHA512" => SHA512.Create(), + _ => throw new ArgumentException($"Unknown hash algorithm name: {algorithmName}.") + }; + + // When + Hash candidate = Hash.Compute(algorithm, stream); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Hash.Compute should produce the expected hash using a stream and two rounds")] + [InlineData("abc123", "MD5", "b106dc6352e5ec1f8aafd8c406d34d92")] + [InlineData("abc123", "SHA1", "6691484ea6b50ddde1926a220da01fa9e575c18a")] + [InlineData("abc123", "SHA256", "efaaeb3b1d1d85e8587ef0527ca43b9575ce8149ba1ee41583d3d19bd130daf8")] + [InlineData("abc123", "SHA384", "d58e9a112b8c637df5d2e33af03ce738dd1c57657243d70d2fa8f76a99fa9a0e2f4abf50d9a88e8958f2d5f6fa002190")] + [InlineData("abc123", "SHA512", "c2c9d705d7a1ed34247649bbe64c6edd2035e0a4c9ae1c063170f5ee2aeca09125cc0a8b30593c07a18801d6e0570de22e8dc40a59bc1f59a49834c05ed49949")] + public void HashComputeShouldProduceTheExpectedHashUsingAStreamAndTwoRounds(string data, string algorithmName, string expected) + { + // Given + Stream stream = new MemoryStream(data.ToByteArray()); + HashAlgorithm algorithm = algorithmName switch + { + "MD5" => MD5.Create(), + "SHA1" => SHA1.Create(), + "SHA256" => SHA256.Create(), + "SHA384" => SHA384.Create(), + "SHA512" => SHA512.Create(), + _ => throw new ArgumentException($"Unknown hash algorithm name: {algorithmName}.") + }; + + // When + Hash candidate = Hash.Compute(algorithm, stream, 2); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Hash.ComputeAsync should produce the expected hash using a stream")] + [InlineData("abc123", "MD5", "e99a18c428cb38d5f260853678922e03")] + [InlineData("abc123", "SHA1", "6367c48dd193d56ea7b0baad25b19455e529f5ee")] + [InlineData("abc123", "SHA256", "6ca13d52ca70c883e0f0bb101e425a89e8624de51db2d2392593af6a84118090")] + [InlineData("abc123", "SHA384", "a31d79891919cad24f3264479d76884f581bee32e86778373db3a124de975dd86a40fc7f399b331133b281ab4b11a6ca")] + [InlineData("abc123", "SHA512", "c70b5dd9ebfb6f51d09d4132b7170c9d20750a7852f00680f65658f0310e810056e6763c34c9a00b0e940076f54495c169fc2302cceb312039271c43469507dc")] + public async void HashComputeAsyncShouldProduceTheExpectedHashUsingAStream(string data, string algorithmName, string expected) + { + // Given + Stream stream = new MemoryStream(data.ToByteArray()); + HashAlgorithm algorithm = algorithmName switch + { + "MD5" => MD5.Create(), + "SHA1" => SHA1.Create(), + "SHA256" => SHA256.Create(), + "SHA384" => SHA384.Create(), + "SHA512" => SHA512.Create(), + _ => throw new ArgumentException($"Unknown hash algorithm name: {algorithmName}.") + }; + + // When + Hash candidate = await Hash.ComputeAsync(algorithm, stream); + string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Fact(DisplayName = "Parse should be able to parse a known hash")] - public void ParseShouldBeAbleToParseAKnownHash() + [Theory(DisplayName = "Hash.ComputeAsync should produce the expected hash using a stream and two rounds")] + [InlineData("abc123", "MD5", "b106dc6352e5ec1f8aafd8c406d34d92")] + [InlineData("abc123", "SHA1", "6691484ea6b50ddde1926a220da01fa9e575c18a")] + [InlineData("abc123", "SHA256", "efaaeb3b1d1d85e8587ef0527ca43b9575ce8149ba1ee41583d3d19bd130daf8")] + [InlineData("abc123", "SHA384", "d58e9a112b8c637df5d2e33af03ce738dd1c57657243d70d2fa8f76a99fa9a0e2f4abf50d9a88e8958f2d5f6fa002190")] + [InlineData("abc123", "SHA512", "c2c9d705d7a1ed34247649bbe64c6edd2035e0a4c9ae1c063170f5ee2aeca09125cc0a8b30593c07a18801d6e0570de22e8dc40a59bc1f59a49834c05ed49949")] + public async void HashComputeAsyncShouldProduceTheExpectedHashUsingAStreamAndTwoRounds(string data, string algorithmName, string expected) { - // Arrange - const string expected = "Sha2Hash256:dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f"; + // Given + Stream stream = new MemoryStream(data.ToByteArray()); + HashAlgorithm algorithm = algorithmName switch + { + "MD5" => MD5.Create(), + "SHA1" => SHA1.Create(), + "SHA256" => SHA256.Create(), + "SHA384" => SHA384.Create(), + "SHA512" => SHA512.Create(), + _ => throw new ArgumentException($"Unknown hash algorithm name: {algorithmName}.") + }; - // Act - Hash hash = Hash.Parse(expected); - string actual = hash.ToStringWithAlgorithmType(); + // When + Hash candidate = await Hash.ComputeAsync(algorithm, stream, 2); + string actual = candidate.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } - [Fact(DisplayName = "Parse should be able to parse an unknown hash")] - public void ParseShouldBeAbleToParseAnUnknownHash() + [Fact(DisplayName = "Hash.Concatenate should produce the expected result")] + public void HashConcatenateShouldProduceExpectedResult() { - // Arrange - const string value = "dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f"; - const string expected = "Unknown:dffd6021bb2bd5b0af676290809ec3a53191dd81c7f70a4b28688a362182986f"; + // Given + using HashAlgorithm algorithm = SHA256.Create(); + Hash left = Hash.Compute(algorithm, "abc"); + Hash right = Hash.Compute(algorithm, "123"); + const string expected = "c1702b0f46b4a0d3ef1e19feef861727cc583a157594e264571126818c820592"; - // Act - Hash hash = Hash.Parse(value); - string actual = hash.ToStringWithAlgorithmType(); + // When + Hash concatenated = left.Concatenate(algorithm, right); + string actual = concatenated.ToString(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs deleted file mode 100644 index d113d43..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/HmacAsyncTests.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class HmacAsyncTests -{ - [Fact(DisplayName = "Identical HMACs should be considered equal")] - public async void IdenticalHashesShouldBeConsideredEqual() - { - // Arrange - Hmac a = await Hmac.ComputeSha2Hmac256Async("abcdefghijklmnopqrstuvwxyz", "key"); - Hmac b = await Hmac.ComputeSha2Hmac256Async("abcdefghijklmnopqrstuvwxyz", "key"); - - // Assert - Assert.Equal(a, b); - } - - [Fact(DisplayName = "Different HMACs should not be considered equal (different data)")] - public async void DifferentHashesShouldNotBeConsideredEqualWithDifferentData() - { - // Arrange - Hmac a = await Hmac.ComputeSha2Hmac256Async("abcdefghijklmnopqrstuvwxyz", "key"); - Hmac b = await Hmac.ComputeSha2Hmac256Async("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "key"); - - // Assert - Assert.NotEqual(a, b); - } - - [Fact(DisplayName = "Different HMACs should not be considered equal (different keys)")] - public async void DifferentHashesShouldNotBeConsideredEqualWithDifferentKeys() - { - // Arrange - Hmac a = await Hmac.ComputeSha2Hmac256Async("abcdefghijklmnopqrstuvwxyz", "key"); - Hmac b = await Hmac.ComputeSha2Hmac256Async("abcdefghijklmnopqrstuvwxyz", "123"); - - // Assert - Assert.NotEqual(a, b); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs b/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs deleted file mode 100644 index 03df0f0..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/HmacTests.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class HmacTests -{ - [Fact(DisplayName = "Identical Hmac values produce identical hash codes.")] - public void IdenticalHmacValuesProduceIdenticalHashCodes() - { - // Arrange - Hmac a = Hmac.ComputeSha2Hmac256("abcdefghijklmnopqrstuvwxyz", "key"); - Hmac b = Hmac.ComputeSha2Hmac256("abcdefghijklmnopqrstuvwxyz", "key"); - - // Act - int hashCodeA = a.GetHashCode(); - int hashCodeB = b.GetHashCode(); - - // Assert - Assert.Equal(hashCodeA, hashCodeB); - } - - [Fact(DisplayName = "Identical HMACs should be considered equal")] - public void IdenticalHashesShouldBeConsideredEqual() - { - // Arrange - Hmac a = Hmac.ComputeSha2Hmac256("abcdefghijklmnopqrstuvwxyz", "key"); - Hmac b = Hmac.ComputeSha2Hmac256("abcdefghijklmnopqrstuvwxyz", "key"); - - // Assert - Assert.Equal(a, b); - } - - [Fact(DisplayName = "Different HMACs should not be considered equal (different data)")] - public void DifferentHashesShouldNotBeConsideredEqualWithDifferentData() - { - // Arrange - Hmac a = Hmac.ComputeSha2Hmac256("abcdefghijklmnopqrstuvwxyz", "key"); - Hmac b = Hmac.ComputeSha2Hmac256("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "key"); - - // Assert - Assert.NotEqual(a, b); - } - - [Fact(DisplayName = "Different HMACs should not be considered equal (different keys)")] - public void DifferentHashesShouldNotBeConsideredEqualWithDifferentKeys() - { - // Arrange - Hmac a = Hmac.ComputeSha2Hmac256("abcdefghijklmnopqrstuvwxyz", "key"); - Hmac b = Hmac.ComputeSha2Hmac256("abcdefghijklmnopqrstuvwxyz", "123"); - - // Assert - Assert.NotEqual(a, b); - } - - [Fact(DisplayName = "Parse should be able to parse a known hash")] - public void ParseShouldBeAbleToParseAKnownHash() - { - // Arrange - const string expected = - "Sha2Hmac256:73ac6fa8599f4bde8dfee594c7f5f6ff03023b2d99ca71a7eccf729a8fc5c324:48656c6c6f2c20576f726c6421"; - - // Act - Hmac hash = Hmac.Parse(expected); - string actual = hash.ToStringWithAlgorithmType(); - - // Assert - Assert.Equal(expected, actual); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs deleted file mode 100644 index 6607122..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/KeyTestBase.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public abstract class KeyTestBase -{ - protected static byte[] GenerateRandomData(int length = 1024) - { - byte[] result = new byte[length]; - Random random = new(Guid.NewGuid().GetHashCode()); - - random.NextBytes(result); - - return result; - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs index 8ea8b61..4714f0e 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeGenericTests.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,38 +15,42 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; using OnixLabs.Core; -using OnixLabs.Core.Collections; -using OnixLabs.Security.Cryptography.UnitTests.Data.Objects; +using OnixLabs.Security.Cryptography.UnitTests.Data; using Xunit; namespace OnixLabs.Security.Cryptography.UnitTests; public sealed class MerkleTreeGenericTests { - private readonly IEnumerable setA = EnumerableOf( + private static readonly HashAlgorithm Algorithm = SHA256.Create(); + + private readonly IEnumerable setA = + [ new MerkleNode("abc", 123, "1953-05-08T01:00:59Z".ToDateTime(), Guid.Parse("18d1e14c-9762-4b2c-8774-3f053e8579e0")), new MerkleNode("def", 456, "1953-05-08T06:30:00Z".ToDateTime(), Guid.Parse("a5d0ad36-f9a6-4fb0-9374-aa658eb19a51")), new MerkleNode("hij", 789, "1953-05-08T12:00:33Z".ToDateTime(), Guid.Parse("0d324d48-d451-416e-ac4d-fed1a324d446")), new MerkleNode("klm", 101, "1953-05-08T18:30:00Z".ToDateTime(), Guid.Parse("dc2bb378-114e-4f5d-8674-92729a67fe3d")), new MerkleNode("nop", 112, "1953-05-08T23:00:59Z".ToDateTime(), Guid.Parse("193863c7-3bfa-4a3c-874a-a99d98b38358")) - ); + ]; - private readonly IEnumerable setB = EnumerableOf( + private readonly IEnumerable setB = + [ new MerkleNode("qrs", 123, "1900-05-08T01:00:59Z".ToDateTime(), Guid.Parse("893576c9-7cb1-4653-a7c4-21e5ba9e7275")), new MerkleNode("tuv", 456, "1901-05-08T06:30:00Z".ToDateTime(), Guid.Parse("e7543a7e-3a52-48f5-842e-9448931f1cde")), new MerkleNode("qxy", 789, "1902-05-08T12:00:33Z".ToDateTime(), Guid.Parse("d228ab75-d36a-4392-9c51-888a5b7f9db7")), new MerkleNode("zab", 101, "1903-05-08T18:30:00Z".ToDateTime(), Guid.Parse("f73180c0-1fc8-4492-ae5d-f0b8962177a8")) - ); + ]; [Fact(DisplayName = "Identical Merkle trees should be considered equal")] public void IdenticalMerkleTreesShouldBeConsideredEqual() { - // Arrange / Act - MerkleTree a = MerkleTree.Create(setA); - MerkleTree b = MerkleTree.Create(setA); + // Given / When + MerkleTree a = MerkleTree.Create(setA, Algorithm); + MerkleTree b = MerkleTree.Create(setA, Algorithm); - // Assert + // Then Assert.Equal(a, b); Assert.Equal(a.Hash, b.Hash); } @@ -54,11 +58,11 @@ public void IdenticalMerkleTreesShouldBeConsideredEqual() [Fact(DisplayName = "Different Merkle trees should not be considered equal")] public void DifferentMerkleTreesShouldNotBeConsideredEqual() { - // Arrange / Act - MerkleTree a = MerkleTree.Create(setA); - MerkleTree b = MerkleTree.Create(setB); + // Given / When + MerkleTree a = MerkleTree.Create(setA, Algorithm); + MerkleTree b = MerkleTree.Create(setB, Algorithm); - // Assert + // Then Assert.NotEqual(a, b); Assert.NotEqual(a.Hash, b.Hash); } @@ -66,40 +70,40 @@ public void DifferentMerkleTreesShouldNotBeConsideredEqual() [Fact(DisplayName = "MerkleTree.GetLeafHashes should produce the same leaf hashes that the tree was constructed with")] public void MerkleTreeGetLeafHashesShouldProduceTheSameLeafHashesThatTheTreeWasConstructedWith() { - // Arrange - IEnumerable expected = setA.Select(value => value.ComputeHash()); - MerkleTree candidate = MerkleTree.Create(setA); + // Given + IEnumerable expected = setA.Select(value => value.ComputeHash(Algorithm)); + MerkleTree candidate = MerkleTree.Create(setA, Algorithm); - // Act + // When IEnumerable actual = candidate.GetLeafHashes(); - // Assert + // Then Assert.Equal(expected, actual); } [Fact(DisplayName = "MerkleTree.GetLeafValues should produce the same leaf values that the tree was constructed with")] public void MerkleTreeGetLeafValuesShouldProduceTheSameLeafValuesThatTheTreeWasConstructedWith() { - // Arrange - MerkleTree candidate = MerkleTree.Create(setA); + // Given + MerkleTree candidate = MerkleTree.Create(setA, Algorithm); - // Act + // When IEnumerable actual = candidate.GetLeafValues(); - // Assert + // Then Assert.Equal(setA, actual); } [Fact(DisplayName = "MerkleTree.ToMerkleTree should produce a hash-only, non-generic Merkle tree that is equal in value")] public void MerkleTreeToMerkleTreeShouldProduceAHashOnlyNonGenericMerkleTreeThatIsEqualInValue() { - // Arrange - MerkleTree a = MerkleTree.Create(setA); + // Given + MerkleTree a = MerkleTree.Create(setA, Algorithm); - // Act - MerkleTree b = a.ToMerkleTree(); + // When + MerkleTree b = a.ToMerkleTree(Algorithm); - // Assert + // Then Assert.Equal(a, b); Assert.Equal(a.Hash, b.Hash); } diff --git a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs index 36cb609..8a29552 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/MerkleTreeTests.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,23 +14,26 @@ using System.Collections.Generic; using System.Linq; +using System.Security.Cryptography; using Xunit; namespace OnixLabs.Security.Cryptography.UnitTests; public sealed class MerkleTreeTests { - private readonly IEnumerable setA = Enumerable.Range(123, 1357).Select(i => Hash.ComputeSha2Hash256($"A{i}")).ToList(); - private readonly IEnumerable setB = Enumerable.Range(100, 1000).Select(i => Hash.ComputeSha2Hash256($"B{i}")).ToList(); + private static readonly HashAlgorithm Algorithm = SHA256.Create(); + + private readonly IEnumerable setA = Enumerable.Range(123, 1357).Select(i => Hash.Compute(Algorithm, $"A{i}")).ToList(); + private readonly IEnumerable setB = Enumerable.Range(100, 1000).Select(i => Hash.Compute(Algorithm, $"B{i}")).ToList(); [Fact(DisplayName = "Identical Merkle trees should be considered equal")] public void IdenticalMerkleTreesShouldBeConsideredEqual() { - // Arrange / Act - MerkleTree a = MerkleTree.Create(setA); - MerkleTree b = MerkleTree.Create(setA); + // Given / When + MerkleTree a = MerkleTree.Create(setA, Algorithm); + MerkleTree b = MerkleTree.Create(setA, Algorithm); - // Assert + // Then Assert.Equal(a, b); Assert.Equal(a.Hash, b.Hash); } @@ -38,11 +41,11 @@ public void IdenticalMerkleTreesShouldBeConsideredEqual() [Fact(DisplayName = "Different Merkle trees should not be considered equal")] public void DifferentMerkleTreesShouldNotBeConsideredEqual() { - // Arrange / Act - MerkleTree a = MerkleTree.Create(setA); - MerkleTree b = MerkleTree.Create(setB); + // Given / When + MerkleTree a = MerkleTree.Create(setA, Algorithm); + MerkleTree b = MerkleTree.Create(setB, Algorithm); - // Assert + // Then Assert.NotEqual(a, b); Assert.NotEqual(a.Hash, b.Hash); } @@ -50,31 +53,31 @@ public void DifferentMerkleTreesShouldNotBeConsideredEqual() [Fact(DisplayName = "MerkleTree.GetLeafHashes should produce the same leaf hashes that the tree was constructed with")] public void MerkleTreeGetLeafHashesShouldProduceTheSameLeafHashesThatTheTreeWasConstructedWith() { - // Arrange - MerkleTree candidate = MerkleTree.Create(setA); + // Given + MerkleTree candidate = MerkleTree.Create(setA, Algorithm); - // Act + // When IEnumerable actual = candidate.GetLeafHashes(); - // Assert + // Then Assert.Equal(setA, actual); } [Fact(DisplayName = "MerkleTree.GetLeafHashes should obtain all leaf hashes from a Merkle tree constructed with 1 million hashes")] public void MerkleTreeGetLeafHashesShouldObtainAllLeafHashesFromAMerkleTreeConstructedWith1MillionHashes() { - // Arrange + // Given IEnumerable expected = Enumerable .Range(0, 1_000_000) - .Select(value => Hash.ComputeSha2Hash256(value.ToString())) + .Select(value => Hash.Compute(Algorithm, value.ToString())) .ToList(); - MerkleTree tree = MerkleTree.Create(expected); + MerkleTree tree = MerkleTree.Create(expected, Algorithm); - // Act + // When IEnumerable actual = tree.GetLeafHashes(); - // Assert + // Then Assert.Equal(expected, actual); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj index a8af21c..39b888f 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj +++ b/OnixLabs.Security.Cryptography.UnitTests/OnixLabs.Security.Cryptography.UnitTests.csproj @@ -22,6 +22,5 @@ - diff --git a/OnixLabs.Security.Cryptography.UnitTests/PrivateKeyTests.cs b/OnixLabs.Security.Cryptography.UnitTests/PrivateKeyTests.cs new file mode 100644 index 0000000..be25240 --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests/PrivateKeyTests.cs @@ -0,0 +1,124 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Security.Cryptography.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Security.Cryptography.UnitTests; + +public sealed class PrivateKeyTests +{ + [Fact(DisplayName = "PrivateKey should be constructable from bytes")] + public void PrivateKeyShouldBeConstructableFromBytes() + { + // Given + byte[] value = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + const string expected = "000102030405060708090a0b0c0d0e0f"; + + // When + PrivateKey candidate = new TestPrivateKey(value); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "PrivateKey value should not be modified when altering the original byte array")] + public void PrivateKeyValueShouldNotBeModifiedWhenAlteringTheOriginalByteArray() + { + // Given + byte[] value = [1, 2, 3, 4]; + PrivateKey candidate = new TestPrivateKey(value); + const string expected = "01020304"; + + // When + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "PrivateKey value should not be modified when altering the obtained byte array")] + public void PrivateKeyValueShouldNotBeModifiedWhenAlteringTheObtainedByteArray() + { + // Given + PrivateKey candidate = new TestPrivateKey([1, 2, 3, 4]); + const string expected = "01020304"; + + // When + byte[] value = candidate.ToByteArray(); + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Identical public key values should be considered equal")] + public void IdenticalPrivateKeyValuesShouldBeConsideredEqual() + { + // Given + PrivateKey left = new TestPrivateKey([1, 2, 3, 4]); + PrivateKey right = new TestPrivateKey([1, 2, 3, 4]); + + // Then + Assert.Equal(left, right); + Assert.True(left.Equals(right)); + Assert.True(left == right); + } + + [Fact(DisplayName = "Different public key values should not be considered equal")] + public void DifferentPrivateKeyValuesShouldNotBeConsideredEqual() + { + // Given + PrivateKey left = new TestPrivateKey([1, 2, 3, 4]); + PrivateKey right = new TestPrivateKey([5, 6, 7, 8]); + + // Then + Assert.NotEqual(left, right); + Assert.False(left.Equals(right)); + Assert.True(left != right); + } + + [Fact(DisplayName = "Identical public key values should produce identical hash codes")] + public void IdenticalPrivateKeyValuesShouldProduceIdenticalPrivateKeyCodes() + { + // Given + PrivateKey left = new TestPrivateKey([1, 2, 3, 4]); + PrivateKey right = new TestPrivateKey([1, 2, 3, 4]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.Equal(leftHashCode, rightHashCode); + } + + [Fact(DisplayName = "Different public key values should produce different hash codes")] + public void DifferentPrivateKeyValuesShouldProduceDifferentPrivateKeyCodes() + { + // Given + PrivateKey left = new TestPrivateKey([1, 2, 3, 4]); + PrivateKey right = new TestPrivateKey([5, 6, 7, 8]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.NotEqual(leftHashCode, rightHashCode); + } +} diff --git a/OnixLabs.Security.Cryptography.UnitTests/PublicKeyTests.cs b/OnixLabs.Security.Cryptography.UnitTests/PublicKeyTests.cs new file mode 100644 index 0000000..162f1b1 --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests/PublicKeyTests.cs @@ -0,0 +1,124 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using OnixLabs.Security.Cryptography.UnitTests.Data; +using Xunit; + +namespace OnixLabs.Security.Cryptography.UnitTests; + +public sealed class PublicKeyTests +{ + [Fact(DisplayName = "PublicKey should be constructable from bytes")] + public void PublicKeyShouldBeConstructableFromBytes() + { + // Given + byte[] value = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + const string expected = "000102030405060708090a0b0c0d0e0f"; + + // When + PublicKey candidate = new TestPublicKey(value); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "PublicKey value should not be modified when altering the original byte array")] + public void PublicKeyValueShouldNotBeModifiedWhenAlteringTheOriginalByteArray() + { + // Given + byte[] value = [1, 2, 3, 4]; + PublicKey candidate = new TestPublicKey(value); + const string expected = "01020304"; + + // When + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "PublicKey value should not be modified when altering the obtained byte array")] + public void PublicKeyValueShouldNotBeModifiedWhenAlteringTheObtainedByteArray() + { + // Given + PublicKey candidate = new TestPublicKey([1, 2, 3, 4]); + const string expected = "01020304"; + + // When + byte[] value = candidate.ToByteArray(); + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Identical public key values should be considered equal")] + public void IdenticalPublicKeyValuesShouldBeConsideredEqual() + { + // Given + PublicKey left = new TestPublicKey([1, 2, 3, 4]); + PublicKey right = new TestPublicKey([1, 2, 3, 4]); + + // Then + Assert.Equal(left, right); + Assert.True(left.Equals(right)); + Assert.True(left == right); + } + + [Fact(DisplayName = "Different public key values should not be considered equal")] + public void DifferentPublicKeyValuesShouldNotBeConsideredEqual() + { + // Given + PublicKey left = new TestPublicKey([1, 2, 3, 4]); + PublicKey right = new TestPublicKey([5, 6, 7, 8]); + + // Then + Assert.NotEqual(left, right); + Assert.False(left.Equals(right)); + Assert.True(left != right); + } + + [Fact(DisplayName = "Identical public key values should produce identical hash codes")] + public void IdenticalPublicKeyValuesShouldProduceIdenticalPublicKeyCodes() + { + // Given + PublicKey left = new TestPublicKey([1, 2, 3, 4]); + PublicKey right = new TestPublicKey([1, 2, 3, 4]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.Equal(leftHashCode, rightHashCode); + } + + [Fact(DisplayName = "Different public key values should produce different hash codes")] + public void DifferentPublicKeyValuesShouldProduceDifferentPublicKeyCodes() + { + // Given + PublicKey left = new TestPublicKey([1, 2, 3, 4]); + PublicKey right = new TestPublicKey([5, 6, 7, 8]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.NotEqual(leftHashCode, rightHashCode); + } +} diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs deleted file mode 100644 index 858cc8f..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyEncryptedPkcs8Tests.cs +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Collections.Generic; -using System.Security.Cryptography; -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class RsaKeyEncryptedPkcs8Tests : KeyTestBase -{ - [Fact(DisplayName = "Two identical RSA PKCS #8 private keys should be considered equal")] - public void TwoIdenticalPrivateKeysShouldBeConsideredEqual() - { - // Arrange - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - const string password = "This is a secret!"; - PbeParameters parameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 64); - - // Act - byte[] pkcs8PrivateKey = privateKey1.ExportPkcs8Key(password, parameters); - PrivateKey privateKey2 = RsaPrivateKey.ImportPkcs8Key(pkcs8PrivateKey, password, type, padding); - - // Assert - Assert.Equal(privateKey1, privateKey2); - } - - [Fact(DisplayName = "Two identical RSA PKCS #8 keys should be able to sign and verify the same data")] - public void TwoIdenticalRsaKeysShouldBeAbleToSignAndVerifyTheSameData() - { - // Arrange - IList<(DigitalSignature, byte[])> signatures = new List<(DigitalSignature, byte[])>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - const string password = "This is a secret!"; - PbeParameters parameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 64); - byte[] pkcs8PrivateKey = privateKey1.ExportPkcs8Key(password, parameters); - PrivateKey privateKey2 = RsaPrivateKey.ImportPkcs8Key(pkcs8PrivateKey, password, type, padding); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - DigitalSignature signature1 = privateKey1.SignData(data); - DigitalSignature signature2 = privateKey2.SignData(data); - - signatures.Add((signature1, data)); - signatures.Add((signature2, data)); - } - - // Assert - foreach ((DigitalSignature signature, byte[] data) in signatures) - { - Assert.True(signature.IsDataValid(data, publicKey1)); - Assert.True(signature.IsDataValid(data, publicKey2)); - } - } - - [Fact(DisplayName = "Two identical RSA PKCS #8 keys should be able to sign and verify the same hash")] - public void TwoIdenticalRsaKeysShouldBeAbleToSignAndVerifyTheSameHash() - { - // Arrange - IList<(DigitalSignature, Hash)> signatures = new List<(DigitalSignature, Hash)>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - const string password = "This is a secret!"; - PbeParameters parameters = new(PbeEncryptionAlgorithm.Aes256Cbc, HashAlgorithmName.SHA256, 64); - byte[] pkcs8PrivateKey = privateKey1.ExportPkcs8Key(password, parameters); - PrivateKey privateKey2 = RsaPrivateKey.ImportPkcs8Key(pkcs8PrivateKey, password, type, padding); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - Hash hashedData = Hash.ComputeSha2Hash256(data); - DigitalSignature signature1 = privateKey1.SignHash(hashedData); - DigitalSignature signature2 = privateKey2.SignHash(hashedData); - - signatures.Add((signature1, hashedData)); - signatures.Add((signature2, hashedData)); - } - - // Assert - foreach ((DigitalSignature signature, Hash hashedData) in signatures) - { - Assert.True(signature.IsHashValid(hashedData, publicKey1)); - Assert.True(signature.IsHashValid(hashedData, publicKey2)); - } - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs deleted file mode 100644 index 86f9e4d..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyPkcs8Tests.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Collections.Generic; -using System.Security.Cryptography; -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class RsaKeyPkcs8Tests : KeyTestBase -{ - [Fact(DisplayName = "Two identical RSA PKCS #8 private keys should be considered equal")] - public void TwoIdenticalPrivateKeysShouldBeConsideredEqual() - { - // Arrange - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - - // Act - byte[] pkcs8PrivateKey = privateKey1.ExportPkcs8Key(); - PrivateKey privateKey2 = RsaPrivateKey.ImportPkcs8Key(pkcs8PrivateKey, type, padding); - - // Assert - Assert.Equal(privateKey1, privateKey2); - } - - [Fact(DisplayName = "Two identical RSA PKCS #8 keys should be able to sign and verify the same data")] - public void TwoIdenticalRsaKeysShouldBeAbleToSignAndVerifyTheSameData() - { - // Arrange - IList<(DigitalSignature, byte[])> signatures = new List<(DigitalSignature, byte[])>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = RsaPrivateKey.ImportPkcs8Key(privateKey1.ExportPkcs8Key(), type, padding); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - DigitalSignature signature1 = privateKey1.SignData(data); - DigitalSignature signature2 = privateKey2.SignData(data); - - signatures.Add((signature1, data)); - signatures.Add((signature2, data)); - } - - // Assert - foreach ((DigitalSignature signature, byte[] data) in signatures) - { - Assert.True(signature.IsDataValid(data, publicKey1)); - Assert.True(signature.IsDataValid(data, publicKey2)); - } - } - - [Fact(DisplayName = "Two identical RSA PKCS #8 keys should be able to sign and verify the same hash")] - public void TwoIdenticalRsaKeysShouldBeAbleToSignAndVerifyTheSameHash() - { - // Arrange - IList<(DigitalSignature, Hash)> signatures = new List<(DigitalSignature, Hash)>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = RsaPrivateKey.ImportPkcs8Key(privateKey1.ExportPkcs8Key(), type, padding); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - Hash hashedData = Hash.ComputeSha2Hash256(data); - DigitalSignature signature1 = privateKey1.SignHash(hashedData); - DigitalSignature signature2 = privateKey2.SignHash(hashedData); - - signatures.Add((signature1, hashedData)); - signatures.Add((signature2, hashedData)); - } - - // Assert - foreach ((DigitalSignature signature, Hash hashedData) in signatures) - { - Assert.True(signature.IsHashValid(hashedData, publicKey1)); - Assert.True(signature.IsHashValid(hashedData, publicKey2)); - } - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs index 284ba01..5954ab2 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/RsaKeyTests.cs @@ -1,122 +1,44 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using System.Collections.Generic; using System.Security.Cryptography; -using OnixLabs.Core.Text; using Xunit; namespace OnixLabs.Security.Cryptography.UnitTests; -public sealed class RsaKeyTests : KeyTestBase +public sealed class RsaKeyTests { - [Fact(DisplayName = "Two identical RSA private keys should be considered equal")] - public void TwoIdenticalPrivateKeysShouldBeConsideredEqual() + [Fact(DisplayName = "RSA sign and verify with two identical keys should succeed")] + public void RsaSignAndVerifyWithTwoIdenticalKeysShouldSucceed() { - // Arrange - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - - // Act - Base58 base58PrivateKey = privateKey1.ToBase58(); - PrivateKey privateKey2 = RsaPrivateKey.Create(base58PrivateKey, type, padding); - - // Assert - Assert.Equal(privateKey1, privateKey2); - } - - [Fact(DisplayName = "Two identical RSA public keys should be considered equal")] - public void TwoIdenticalPublicKeysShouldBeConsideredEqual() - { - // Arrange - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PublicKey publicKey1 = pair.PublicKey; - - // Act - Base58 base58PublicKey = publicKey1.ToBase58(); - PublicKey publicKey2 = RsaPublicKey.Create(base58PublicKey, type, padding); - - // Assert - Assert.Equal(publicKey1, publicKey2); - } - - [Fact(DisplayName = "Two identical RSA keys should be able to sign and verify the same data")] - public void TwoIdenticalRsaKeysShouldBeAbleToSignAndVerifyTheSameData() - { - // Arrange - IList<(DigitalSignature, byte[])> signatures = new List<(DigitalSignature, byte[])>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = RsaPrivateKey.Create(privateKey1.ToBase64(), type, padding); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - DigitalSignature signature1 = privateKey1.SignData(data); - DigitalSignature signature2 = privateKey2.SignData(data); - - signatures.Add((signature1, data)); - signatures.Add((signature2, data)); - } - - // Assert - foreach ((DigitalSignature signature, byte[] data) in signatures) - { - Assert.True(signature.IsDataValid(data, publicKey1)); - Assert.True(signature.IsDataValid(data, publicKey2)); - } - } - - [Fact(DisplayName = "Two identical RSA keys should be able to sign and verify the same hash")] - public void TwoIdenticalRsaKeysShouldBeAbleToSignAndVerifyTheSameHash() - { - // Arrange - IList<(DigitalSignature, Hash)> signatures = new List<(DigitalSignature, Hash)>(); - HashAlgorithmType type = HashAlgorithmType.Sha2Hash256; - RSASignaturePadding padding = RSASignaturePadding.Pss; - KeyPair pair = KeyPair.CreateRsaKeyPair(type, padding); - PrivateKey privateKey1 = pair.PrivateKey; - PrivateKey privateKey2 = RsaPrivateKey.Create(privateKey1.ToBase64(), type, padding); - PublicKey publicKey1 = pair.PublicKey; - PublicKey publicKey2 = privateKey1.GetPublicKey(); - - // Act - for (int index = 0; index < 5; index++) - { - byte[] data = GenerateRandomData(); - Hash hashedData = Hash.ComputeSha2Hash256(data); - DigitalSignature signature1 = privateKey1.SignHash(hashedData); - DigitalSignature signature2 = privateKey2.SignHash(hashedData); - - signatures.Add((signature1, hashedData)); - signatures.Add((signature2, hashedData)); - } - - // Assert - foreach ((DigitalSignature signature, Hash hashedData) in signatures) - { - Assert.True(signature.IsHashValid(hashedData, publicKey1)); - Assert.True(signature.IsHashValid(hashedData, publicKey2)); - } + // Given + byte[] data = Salt.CreateNonZero(2048).ToByteArray(); + HashAlgorithmName algorithm = HashAlgorithmName.SHA256; + RSASignaturePadding padding = RSASignaturePadding.Pkcs1; + IRsaPrivateKey privateKey1 = RsaPrivateKey.Create(); + IRsaPrivateKey privateKey2 = new RsaPrivateKey(privateKey1.ToByteArray()); + IRsaPublicKey publicKey1 = privateKey1.GetPublicKey(); + IRsaPublicKey publicKey2 = privateKey2.GetPublicKey(); + + // When + DigitalSignature signature1 = new(privateKey1.SignData(data, algorithm, padding)); + DigitalSignature signature2 = new(privateKey2.SignData(data, algorithm, padding)); + + // Then + Assert.True(publicKey1.IsDataValid(signature1, data, algorithm, padding)); + Assert.True(publicKey1.IsDataValid(signature2, data, algorithm, padding)); + Assert.True(publicKey2.IsDataValid(signature1, data, algorithm, padding)); + Assert.True(publicKey2.IsDataValid(signature2, data, algorithm, padding)); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs b/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs index f900e5b..f1b57ef 100644 --- a/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs +++ b/OnixLabs.Security.Cryptography.UnitTests/SaltTests.cs @@ -1,44 +1,147 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using System.Linq; +using OnixLabs.Core.Linq; using Xunit; namespace OnixLabs.Security.Cryptography.UnitTests; public sealed class SaltTests { + [Fact(DisplayName = "Salt should be constructable from bytes")] + public void SaltShouldBeConstructableFromBytes() + { + // Given + byte[] value = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + const string expected = "000102030405060708090a0b0c0d0e0f"; + + // When + Salt candidate = new(value); + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Salt value should not be modified when altering the original byte array")] + public void SaltValueShouldNotBeModifiedWhenAlteringTheOriginalByteArray() + { + // Given + byte[] value = [1, 2, 3, 4]; + Salt candidate = new(value); + const string expected = "01020304"; + + // When + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Salt value should not be modified when altering the obtained byte array")] + public void SaltValueShouldNotBeModifiedWhenAlteringTheObtainedByteArray() + { + // Given + Salt candidate = new([1, 2, 3, 4]); + const string expected = "01020304"; + + // When + byte[] value = candidate.ToByteArray(); + value[0] = 0; + string actual = candidate.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Fact(DisplayName = "Identical salt values should be considered equal")] + public void IdenticalSaltValuesShouldBeConsideredEqual() + { + // Given + Salt left = new([1, 2, 3, 4]); + Salt right = new([1, 2, 3, 4]); + + // Then + Assert.Equal(left, right); + Assert.True(left.Equals(right)); + Assert.True(left == right); + } + + [Fact(DisplayName = "Different salt values should not be considered equal")] + public void DifferentSaltValuesShouldNotBeConsideredEqual() + { + // Given + Salt left = new([1, 2, 3, 4]); + Salt right = new([5, 6, 7, 8]); + + // Then + Assert.NotEqual(left, right); + Assert.False(left.Equals(right)); + Assert.True(left != right); + } + + [Fact(DisplayName = "Identical salt values should produce identical hash codes")] + public void IdenticalSaltValuesShouldProduceIdenticalSaltCodes() + { + // Given + Salt left = new([1, 2, 3, 4]); + Salt right = new([1, 2, 3, 4]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.Equal(leftHashCode, rightHashCode); + } + + [Fact(DisplayName = "Different salt values should produce different hash codes")] + public void DifferentSaltValuesShouldProduceDifferentSaltCodes() + { + // Given + Salt left = new([1, 2, 3, 4]); + Salt right = new([5, 6, 7, 8]); + + // When + int leftHashCode = left.GetHashCode(); + int rightHashCode = right.GetHashCode(); + + // Then + Assert.NotEqual(leftHashCode, rightHashCode); + } + [Fact(DisplayName = "Salt.Create should produce a salt of the specified length")] public void SaltCreateShouldProduceASaltOfTheSpecifiedLength() { - // Arrange / Act + // Given / When const int expected = 32; Salt candidate = Salt.Create(expected); - // Assert + // Then Assert.Equal(expected, candidate.ToByteArray().Length); } [Fact(DisplayName = "Salt.CreateNonZero should produce a salt of the specified length of non-zero bytes")] public void SaltCreateNonZeroShouldProduceASaltOfTheSpecifiedLengthOfNonZeroBytes() { - // Arrange / Act + // Given / When const int expected = 32; Salt candidate = Salt.CreateNonZero(expected); - // Assert + // Then Assert.Equal(expected, candidate.ToByteArray().Length); - Assert.True(candidate.ToByteArray().All(value => value > 0)); + Assert.True(candidate.ToByteArray().None(value => value is 0)); } } diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs deleted file mode 100644 index e659206..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash224Tests.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class Sha3Hash224Tests : Sha3HashTestBase -{ - protected override Sha3 HashAlgorithm => Sha3.CreateSha3Hash224(); - - [Theory(DisplayName = "Sha3Managed224 should produce the expected hash for the specified string literal")] - [InlineData("6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7", "")] - [InlineData("9877af03f5e1919851d0ef4ce6b23f1e85a40b446d93713f4c6e6dcd", "1234567890")] - [InlineData("beae76edd99d4ad4d398d51c5ea1d8b7b3fa6d49d687b0cb1ec2ec41", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("5cdeca81e123f87cad96b9cba999f16f6d41549608d4e0f4681b8239", "abcdefghijklmnopqrstuvwxyz")] - public override void TestSha3WithLiteralString(string expected, string literal) - { - base.TestSha3WithLiteralString(expected, literal); - } - - [Theory(DisplayName = "Sha3Managed224 should produce the expected hash for the specified string template")] - [InlineData("d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c", "a", 1_000_000)] - public override void TestSha3WithGeneratedString(string expected, string template, int iterations) - { - base.TestSha3WithGeneratedString(expected, template, iterations); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs deleted file mode 100644 index bd7044e..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash256Tests.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class Sha3Hash256Tests : Sha3HashTestBase -{ - protected override Sha3 HashAlgorithm => Sha3.CreateSha3Hash256(); - - [Theory(DisplayName = "Sha3Managed256 should produce the expected hash for the specified string literal")] - [InlineData("a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a", "")] - [InlineData("01da8843e976913aa5c15a62d45f1c9267391dcbd0a76ad411919043f374a163", "1234567890")] - [InlineData("738eeb2d4adf0d452456695011bb252bd4701a0ae78fdd3fc945a963bceb1702", "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData("7cab2dc765e21b241dbc1c255ce620b29f527c6d5e7f5f843e56288f0d707521", "abcdefghijklmnopqrstuvwxyz")] - public override void TestSha3WithLiteralString(string expected, string literal) - { - base.TestSha3WithLiteralString(expected, literal); - } - - [Theory(DisplayName = "Sha3Managed256 should produce a valid hash result for the given string template")] - [InlineData("5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1", "a", 1_000_000)] - public override void TestSha3WithGeneratedString(string expected, string template, int iterations) - { - base.TestSha3WithGeneratedString(expected, template, iterations); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs deleted file mode 100644 index dd41f1b..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash384Tests.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class Sha3Managed384Tests : Sha3HashTestBase -{ - protected override Sha3 HashAlgorithm => Sha3.CreateSha3Hash384(); - - [Theory(DisplayName = "Sha3Managed384 should produce the expected hash for the specified string literal")] - [InlineData( - "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004", - "" - )] - [InlineData( - "6fdddab7d670f202629531c1a51b32ca30696d0af4dd5b0fbb5f82c0aba5e505110455f37d7ef73950c2bb0495a38f56", - "1234567890" - )] - [InlineData( - "284da0df47fc9e75a4ef1248f69ca0d12a5d44508942e63b03b8c227510c2e1b43400009fcd36c0acc941679e5024a04", - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - )] - [InlineData( - "fed399d2217aaf4c717ad0c5102c15589e1c990cc2b9a5029056a7f7485888d6ab65db2370077a5cadb53fc9280d278f", - "abcdefghijklmnopqrstuvwxyz" - )] - public override void TestSha3WithLiteralString(string expected, string literal) - { - base.TestSha3WithLiteralString(expected, literal); - } - - [Theory(DisplayName = "Sha3Managed384 should produce a valid hash result for the given string template")] - [InlineData("eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340", - "a", 1_000_000)] - public override void TestSha3WithGeneratedString(string expected, string template, int iterations) - { - base.TestSha3WithGeneratedString(expected, template, iterations); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs deleted file mode 100644 index ee6545c..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Hash512Tests.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class Sha3Managed512Tests : Sha3HashTestBase -{ - protected override Sha3 HashAlgorithm => Sha3.CreateSha3Hash512(); - - [Theory(DisplayName = "Sha3Managed512 should produce the expected hash for the specified message")] - [InlineData( - "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26", - "")] - [InlineData( - "36dde7d288a2166a651d51ec6ded9e70e72cf6b366293d6f513c75393c57d6f33b949879b9d5e7f7c21cd8c02ede75e74fc54ea15bd043b4df008533fc68ae69", - "1234567890")] - [InlineData( - "69958b041bc72e9922e02cd4250953ee69d5f6e69f97d8def72b34effc0aea2bf5cfe03bd4ada0e271060593395656c1bf9eb68d1fc4cf146f90601152222df7", - "ABCDEFGHIJKLMNOPQRSTUVWXYZ")] - [InlineData( - "af328d17fa28753a3c9f5cb72e376b90440b96f0289e5703b729324a975ab384eda565fc92aaded143669900d761861687acdc0a5ffa358bd0571aaad80aca68", - "abcdefghijklmnopqrstuvwxyz")] - public override void TestSha3WithLiteralString(string expected, string literal) - { - base.TestSha3WithLiteralString(expected, literal); - } - - [Theory(DisplayName = "Sha3Managed512 should produce the expected hash for the specified string template")] - [InlineData( - "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87", - "a", 1_000_000)] - public override void TestSha3WithGeneratedString(string expected, string template, int iterations) - { - base.TestSha3WithGeneratedString(expected, template, iterations); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs deleted file mode 100644 index 3bef195..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3HashTestBase.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public abstract class Sha3HashTestBase -{ - protected abstract Sha3 HashAlgorithm { get; } - - public virtual void TestSha3WithLiteralString(string expected, string literal) - { - string actual = ComputeHash(HashAlgorithm, literal); - Assert.Equal(expected, actual); - } - - public virtual void TestSha3WithGeneratedString(string expected, string template, int iterations) - { - string actual = ComputeHash(HashAlgorithm, string.Concat(Enumerable.Repeat(template, iterations))); - Assert.Equal(expected, actual); - } - - private static string ComputeHash(HashAlgorithm algorithm, string plainText) - { - byte[] plainTextBytes = Encoding.Default.GetBytes(plainText); - byte[] hashedBytes = algorithm.ComputeHash(plainTextBytes); - return Hash.Create(hashedBytes).ToString(); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs deleted file mode 100644 index c958b84..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake128Tests.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class Sha3ManagedShake128Tests : Sha3ShakeTestBase -{ - [Theory(DisplayName = "Sha3ManagedShake128 should produce the expected hash for the specified string literal")] - [InlineData("7f9c2ba4", "", 4)] - [InlineData("7f9c2ba4e88f827d", "", 8)] - [InlineData("7f9c2ba4e88f827d616045507605853e", "", 16)] - [InlineData("7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26", "", 32)] - [InlineData("1cd2c71a", "1234567890", 4)] - [InlineData("1cd2c71a52e3f2a6", "1234567890", 8)] - [InlineData("1cd2c71a52e3f2a620173e915f17648d", "1234567890", 16)] - [InlineData("1cd2c71a52e3f2a620173e915f17648dcc43443ef78754302c6b44cf47daf527", "1234567890", 32)] - [InlineData("5b3b6a58", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 4)] - [InlineData("5b3b6a587417f8fa", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 8)] - [InlineData("5b3b6a587417f8fa192aba21c16b7b7a", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 16)] - [InlineData("5b3b6a587417f8fa192aba21c16b7b7a6375aac5f04e950f", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 24)] - [InlineData("961c919c", "abcdefghijklmnopqrstuvwxyz", 4)] - [InlineData("961c919c0854576e", "abcdefghijklmnopqrstuvwxyz", 8)] - [InlineData("961c919c0854576e561320e81514bf37", "abcdefghijklmnopqrstuvwxyz", 16)] - [InlineData("961c919c0854576e561320e81514bf3724197d0715e16a36", "abcdefghijklmnopqrstuvwxyz", 24)] - public override void TestSha3WithLiteralString(string expected, string literal, int length) - { - HashAlgorithm = Sha3.CreateSha3Shake128(length); - base.TestSha3WithLiteralString(expected, literal, length); - } - - [Theory(DisplayName = "Sha3ManagedShake128 should produce the expected hash for the specified string template")] - [InlineData("9d222c79", "a", 1_000_000, 4)] - [InlineData("9d222c79c4ff9d09", "a", 1_000_000, 8)] - [InlineData("9d222c79c4ff9d092cf6ca86143aa411", "a", 1_000_000, 16)] - [InlineData("9d222c79c4ff9d092cf6ca86143aa411e369973808ef97093255826c5572ef58", "a", 1_000_000, 32)] - public override void TestSha3WithGeneratedString(string expected, string template, int iterations, int length) - { - HashAlgorithm = Sha3.CreateSha3Shake128(length); - base.TestSha3WithGeneratedString(expected, template, iterations, length); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs deleted file mode 100644 index 82e0a05..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3Shake256Tests.cs +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public sealed class Sha3ManagedShake256Tests : Sha3ShakeTestBase -{ - [Theory(DisplayName = "Sha3ManagedShake256 should produce the expected hash for the specified string literal")] - [InlineData("46b9dd2b", "", 4)] - [InlineData("46b9dd2b0ba88d13", "", 8)] - [InlineData("46b9dd2b0ba88d13233b3feb743eeb24", "", 16)] - [InlineData("46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762f", "", 32)] - [InlineData("cd65a4e5", "1234567890", 4)] - [InlineData("cd65a4e553405b50", "1234567890", 8)] - [InlineData("cd65a4e553405b50c2f37001ea81905f", "1234567890", 16)] - [InlineData("cd65a4e553405b50c2f37001ea81905f36d650cc775fdad898b2e343644cb3db", "1234567890", 32)] - [InlineData("fa8775b6", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 4)] - [InlineData("fa8775b64bf3aaf1", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 8)] - [InlineData("fa8775b64bf3aaf10d7f473c460f4d23", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 16)] - [InlineData("fa8775b64bf3aaf10d7f473c460f4d2361f56ff34ae7267a", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 24)] - [InlineData("b7b78b04", "abcdefghijklmnopqrstuvwxyz", 4)] - [InlineData("b7b78b04a3dd30a2", "abcdefghijklmnopqrstuvwxyz", 8)] - [InlineData("b7b78b04a3dd30a265c8886c33fda947", "abcdefghijklmnopqrstuvwxyz", 16)] - [InlineData("b7b78b04a3dd30a265c8886c33fda94799853de5d3d10541", "abcdefghijklmnopqrstuvwxyz", 24)] - public override void TestSha3WithLiteralString(string expected, string literal, int length) - { - HashAlgorithm = Sha3.CreateSha3Shake256(length); - base.TestSha3WithLiteralString(expected, literal, length); - } - - [Theory(DisplayName = "Sha3ManagedShake256 should produce the expected hash for the specified string template")] - [InlineData("3578a7a4", "a", 1_000_000, 4)] - [InlineData("3578a7a4ca913756", "a", 1_000_000, 8)] - [InlineData("3578a7a4ca9137569cdf76ed617d31bb", "a", 1_000_000, 16)] - [InlineData("3578a7a4ca9137569cdf76ed617d31bb994fca9c1bbf8b184013de8234dfd13a", "a", 1_000_000, 32)] - public override void TestSha3WithGeneratedString(string expected, string template, int iterations, int length) - { - HashAlgorithm = Sha3.CreateSha3Shake256(length); - base.TestSha3WithGeneratedString(expected, template, iterations, length); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs deleted file mode 100644 index 968fffc..0000000 --- a/OnixLabs.Security.Cryptography.UnitTests/Sha3ShakeTestBase.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using Xunit; - -namespace OnixLabs.Security.Cryptography.UnitTests; - -public abstract class Sha3ShakeTestBase -{ - protected Sha3 HashAlgorithm { get; set; } - - public virtual void TestSha3WithLiteralString(string expected, string literal, int length) - { - string actual = ComputeHash(HashAlgorithm, literal); - Assert.Equal(expected, actual); - } - - public virtual void TestSha3WithGeneratedString(string expected, string template, int iterations, int length) - { - string actual = ComputeHash(HashAlgorithm, string.Concat(Enumerable.Repeat(template, iterations))); - Assert.Equal(expected, actual); - } - - private static string ComputeHash(HashAlgorithm algorithm, string plainText) - { - byte[] plainTextBytes = Encoding.Default.GetBytes(plainText); - byte[] hashedBytes = algorithm.ComputeHash(plainTextBytes); - return Hash.Create(hashedBytes).ToString(); - } -} diff --git a/OnixLabs.Security.Cryptography.UnitTests/Sha3Tests.cs b/OnixLabs.Security.Cryptography.UnitTests/Sha3Tests.cs new file mode 100644 index 0000000..3e22151 --- /dev/null +++ b/OnixLabs.Security.Cryptography.UnitTests/Sha3Tests.cs @@ -0,0 +1,601 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Security.Cryptography; +using Xunit; + +namespace OnixLabs.Security.Cryptography.UnitTests; + +public sealed class Sha3Tests +{ + [Theory(DisplayName = "Sha3Hash224 should produce the expected result")] + [InlineData('A', "97e2f98c0938943ab1a18a1721a04dff922ecc1ad14d4bbf905c02ca")] + [InlineData('B', "b60bd459170afa28b3ef45a22ce41ede9ad62a9a0b250482a7e1beb6")] + [InlineData('C', "64d7aef1a5121b17a819ed6a6da3ac4930420a916f30acfe909f9482")] + [InlineData('D', "3cc1b4bd4dcd8ecf49d86d4970fa0e3af4a6266f35c2244d8b19a360")] + [InlineData('E', "61886c21370ba76d87ef2ef10ee1f508dbb1f7eeb239786568ac8aa9")] + [InlineData('F', "1e1e62312963bebff717b3b45a47003e0aa77815aee43368b45c2002")] + [InlineData('G', "9fe797ef1f52cf86c139f14aba3beb34225f96e0f3712ee5648fa120")] + [InlineData('H', "2aebfcaa105dea01662466ab8d82e304c374328e622ffaa0e796ae82")] + [InlineData('I', "9439a92d09b67af52e62a43318f9fb5f5f56ff8c5561d66a484966f0")] + [InlineData('J', "0b79dc2770e78755e9f0ec888f7ab92cee97938d19b6aa066c6e6d45")] + [InlineData('K', "5ea1f4dccfd9cf83485c4766180f0b7dbe4cc7bc78435d5b749fc0da")] + [InlineData('L', "90efae0893370cb53c261a30b69fd026d4b1c5c3221bc9a568ac19e3")] + [InlineData('M', "fe908de89314cebfe8e5b5d10e1b800b0e8fc033ef08dccc0d9c295e")] + [InlineData('N', "9c65eb6b181a665acf87a19cafedaff7d48f8b66b50b171a283c9370")] + [InlineData('O', "69a9eed164711b1201e4d3c6db567a3417805ef140d7c2bb168a3ffa")] + [InlineData('P', "49e17197a1d79e6dc7fac1cb5e1a44f08ee151ec3e01188b57842243")] + [InlineData('Q', "8f01734a973963b99c731ddf95c7d64d162674aa4382727a56854cdb")] + [InlineData('R', "2a2d0471bb24c160c7f839b3652f01e292f15aa09278daa1253c88f9")] + [InlineData('S', "aa50f8575a9e0791313375fd0232300a7aea9dd1fcc20c6de991aea0")] + [InlineData('T', "b7cd747c390db6bb6847225755a4aa0f7eeb66363452c45284556dbb")] + [InlineData('U', "35e0a16a4a92f63cab78df6587ec8f227d995516c893d7a966db62a4")] + [InlineData('V', "a0393621904f8a7f08f8f949428af418b609f7fab8e126175d7489be")] + [InlineData('W', "e7e8c042c1b9889070330ee25e12a09a5a01c309308a2322a414b878")] + [InlineData('X', "7b6fc9c4054463d97c8c90dd89049b67bb8f148952c2070eeda1bb86")] + [InlineData('Y', "d738effb07d0b422f4ccc99a822b32fbc926f6ba3d052cca4b1f93c2")] + [InlineData('Z', "f41ad234fb099cc6b05cce263862fe3e06bded3d097671bc8f68ad5f")] + [InlineData('a', "9e86ff69557ca95f405f081269685b38e3a819b309ee942f482b6a8b")] + [InlineData('b', "8ec94b5ae7bae885e5b1fdeaa6fc2ca2af27febfdb7cdfaa6745fd52")] + [InlineData('c', "d77fb1a25346cfaecd2b491c3a3b452f10cda5a5b37842f2bcbfa5b2")] + [InlineData('d', "af81fd2b118fc4b3ed11bd42e7c056de57e29fcde0b0f236adaa4e25")] + [InlineData('e', "6e22f57104bb4b8dea42a97f517f12e9e28d667c97f2ca0c29d55f8a")] + [InlineData('f', "3a9de008f526d239d89905e2203fa484f6e68dfc096a7c051eb80f15")] + [InlineData('g', "84342e0cfccf62d91ef86c2698b3d0294152b8f908bf95fc0273c00d")] + [InlineData('h', "aea0b0e10eac300d286f13946455240a5978a4e4748ea87062f8a45a")] + [InlineData('i', "ca0e1bce24fbaf261d98d7492adac27652a5f9e2ba06f3c0199437bc")] + [InlineData('j', "7689b617e73b395ecfeb897ec177fbe5bf29307c8975dfbf5602ea22")] + [InlineData('k', "4c483a7e33059a013a845d18195bbaf47b0398c4ae117d16255c737e")] + [InlineData('l', "35fd6f346c0b2fa77a32a1c8d961d08450da1cd6494afca64b57955f")] + [InlineData('m', "c3835c6f733db2d1f556e5b2f32f11ad59ad0a7e996a25376951cd81")] + [InlineData('n', "3250c7b05b5f3af6db4e62ac1a75f0697aeb63921007eb81f24e691b")] + [InlineData('o', "25ab1ac565856d499f958012c0842e432050c3988037c7919021f011")] + [InlineData('p', "4295784315214500e4b51a46b3db88b139a811763aa705c5449f962d")] + [InlineData('q', "774057ce10e1b255cfa747982782e969231ef434a057622021ff5b9c")] + [InlineData('r', "d0b8f1b118091fbc0486a81919e2d7171a6310d4892130f33c51aa1d")] + [InlineData('s', "001ad0de4e72638f77b9fa1272d3aa26ac5458b7b3d6f37f1dc1319a")] + [InlineData('t', "bc3858492b7530bf2adafa0ddc6773863e41b8af69cc6da336d32691")] + [InlineData('u', "74d73ebda3f089ec06c9d2e6fbf49a88f8b72d67a98f617d2e19c34d")] + [InlineData('v', "4a7afb90ea8bf1a5c91d22700b7ebfaea729857df2d4797e0acde861")] + [InlineData('w', "297c52529a495674b68a3c8cc129bcdacc123b65e63a54d3e94a44a7")] + [InlineData('x', "63e6ceb28ad474fa51c3d5dda2239adb5e58a1ae2600d18c6e116746")] + [InlineData('y', "5849850aa0264269112e0d8d25f1336e6caf4b9dab34ae092b01f608")] + [InlineData('z', "3360e4f1a619f1628be65abec0da2992d4c7ceab1d2d3671ef4790b7")] + [InlineData('0', "a823c3f51659da24d9a61254e9f61c39a4c8f11fd65820542403dd1c")] + [InlineData('1', "300d01f3a910045fefa16d6a149f38167b2503dbc37c1b24fd6f751e")] + [InlineData('2', "f3ff4f073ed24d62051c8d7bb73418b95db2f6ff9e4441af466f6d98")] + [InlineData('3', "b6f194539618d1e5eec08a56b8c7d09b8198fe1faa3f16e9703b91bd")] + [InlineData('4', "51bbf7daffa13cd37d2517dd38b1be95b200053bd4e36492b5566bda")] + [InlineData('5', "4a63debd3538267188df39677b980ddf64ff563264554210b43524ea")] + [InlineData('6', "970a4c0b7081bd6a245822c7e804d704db34d32acc7b771208a8c24a")] + [InlineData('7', "aa98ecf6824dad085b259424c29f535bc339c94bace0a7a031ec40e6")] + [InlineData('8', "2531506e5f2f02bd42cbbd39b3f8a181e120eb662b5c85471fa913b3")] + [InlineData('9', "2299019d2c50f7525fc39a05256f802de6e9d05328c903d298b03d9d")] + public void Sha3Hash224ShouldProduceExpectedResult(char character, string expected) + { + // Given + using HashAlgorithm algorithm = Sha3.CreateSha3Hash224(); + + // When + Hash hash = Hash.Compute(algorithm, [character]); + string actual = hash.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Sha3Hash226 should produce the expected result")] + [InlineData('A', "1c9ebd6caf02840a5b2b7f0fc870ec1db154886ae9fe621b822b14fd0bf513d6")] + [InlineData('B', "521ec18851e17bbba961bc46c70baf03ee67ebdea11a8306de39c15a90e9d2e5")] + [InlineData('C', "2248e6be26f60c9baa59adbda2a136a4a5305d7b475d8465ba4911b4886e39a5")] + [InlineData('D', "037f4095baddc6f37fde4740c304b1691512d2fc9cf7ede8a93b8c9ec3d1fe07")] + [InlineData('E', "e63a84c18447bfca5c67b20a58fc6a4fefa762e4fa0e6b3b2e46f64daba345e5")] + [InlineData('F', "caf04597f01603582b91c53d5dad9c6c481445b5160a976a44c35ed428b439d7")] + [InlineData('G', "25c69eebe727567130b3e3320395e3ec854138e6ea5034dc79eebcbeb86da200")] + [InlineData('H', "2cee232f0cf383960ac375e090a647e2afd4ebeb12b4cecb1bf91c2e0f4b3408")] + [InlineData('I', "c837f30e97185c362830b324e58a3e6782095ee8457109b27f03819ff516e121")] + [InlineData('J', "5445d3d5a46c7a99219705ea5b6daa7f870b83e721da6f252f2304b94a6d7d05")] + [InlineData('K', "078773c4efc5ce946952e92d25f89d0cdd1603fc21842df386fa55855613e8cb")] + [InlineData('L', "266ddf27cb4fb4223962ef29090bcc4f50e363bca75c581756f605fb91f9c7e8")] + [InlineData('M', "6920014bef534e7eea89545a50d6aef0921f1972efcddce9f22f04a45b47d472")] + [InlineData('N', "345baaa13bbe3a40695db7697fbe3f64206323b77cf3635902106f9f29667361")] + [InlineData('O', "60c4004508ddcd8d1b0ea1c56ed1e5679d756d72e40f1a00820dbe5d9f69ff63")] + [InlineData('P', "e5a73514ffed2f2f59b5112f4ae50cb138f1658633d354ac36c7c1bc019259d2")] + [InlineData('Q', "ba86a2a6dac23e336a34b4337eb740d40d900fae703bf55dcde8430208bb82e8")] + [InlineData('R', "d034b2b544e4ffb619a9c156ae578fe21f38eb0997f097ca9569807ca157f4f6")] + [InlineData('S', "164a93c6619015a4ed2d50a49c0d98252296e3e4c7fa5277656188edb3fe71b7")] + [InlineData('T', "b3291957374e0a836351d5129cf45a5e0f73a92edff7b2c85ef159062301829e")] + [InlineData('U', "78fe1396dda648dcbccc3c17af4cd29de873f2cdf5e4c5eb04e0ef08e86cc267")] + [InlineData('V', "3eecb4a5c11c8bab18ddad1d268c827aaabb17c83f51869832a5af15efdedfcb")] + [InlineData('W', "4cea338a15eccf7f51d8297c2873b1c5d0e5bea7d52eb7e984500b0759937d0d")] + [InlineData('X', "31660a8aa8b0991f2d115272fecba9f9fe21e0798377c2b965405039319a1452")] + [InlineData('Y', "08ad231c95c5b60ab9757d6f95672f4e8731910a8f4573a90a1798ee8127ee94")] + [InlineData('Z', "1fb80b3947f9fa50760bc627a0341d53715fb79013184b34f4c0a306b62fdf05")] + [InlineData('a', "80084bf2fba02475726feb2cab2d8215eab14bc6bdd8bfb2c8151257032ecd8b")] + [InlineData('b', "b039179a8a4ce2c252aa6f2f25798251c19b75fc1508d9d511a191e0487d64a7")] + [InlineData('c', "263ab762270d3b73d3e2cddf9acc893bb6bd41110347e5d5e4bd1d3c128ea90a")] + [InlineData('d', "4ce8765e720c576f6f5a34ca380b3de5f0912e6e3cc5355542c363891e54594b")] + [InlineData('e', "42538602949f370aa331d2c07a1ee7ff26caac9cc676288f94b82eb2188b8465")] + [InlineData('f', "a0b37b8bfae8e71330bd8e278e4a45ca916d00475dd8b85e9352533454c9fec8")] + [InlineData('g', "9f2898da52dedaca29f05bcac0c8e43e4b9f7cb5707c14cc3f35a567232cec7c")] + [InlineData('h', "5a082c81a7e4d5833ee20bd67d2f4d736f679da33e4bebd3838217cb27bec1d3")] + [InlineData('i', "bf872d20c4ef70ab19c9d413f172ce399a30ddeca771658561b1443111069c9e")] + [InlineData('j', "f35e560e05de779f2669b9f513c2a7ab81dfeb100e2f4ee1fb17354bfa2740ca")] + [InlineData('k', "7c712596135d13a73c0dd366151b9440f3e9072371b436371107f12b3d850180")] + [InlineData('l', "3e5e3e723953551a2ba2e7c5584bcc4ce407414af1ab2569051e7c9bfa33164d")] + [InlineData('m', "1b42f48aa4371867a7c51ae6f237f35626e02c12eefa592614e1b10af7769370")] + [InlineData('n', "8ee93ceda95bbe450f7fb53a700c56dfac4387e48eb127881a2a68727bc7810c")] + [InlineData('o', "12c6debe02a118f89049700e723650d269838a76024a826607b163bc2a237031")] + [InlineData('p', "14c68e20d8ddb4dbd248ed14bdb2012cfcee23530af0f71328009d1e90bb36ac")] + [InlineData('q', "8a5e1d339fafc39350fd8cf1d7ca7982091c27f6b77f75bd4ddab3df425b4f8c")] + [InlineData('r', "f695d5fe6e2c67fe29ccf09341c29ad58154c568c5917a919c31936a3c96d607")] + [InlineData('s', "cdc56a5028e51232cb28194fb1eb93e7014d60fb7afb447a49a1e1aaa640c9a4")] + [InlineData('t', "889729e8d2d8864a59db1e195ad67c76949578ff2b4637388564a81dd68fc01e")] + [InlineData('u', "d7e9468290673221249673d2b82c3cb316819a8496c2f2dba3eaebd9477af44c")] + [InlineData('v', "453c8391bbd41309b79d7acc1382c2b0fb5f6b67f686d77c410666336ff9dabb")] + [InlineData('w', "f1cfdca558ac0c00464ca0f3e265ec6fb32c57caeb106fbfed9f174f6b814642")] + [InlineData('x', "741efa311f97686956946758e0d95f70f11ff2da4f2feb7c54314f44134ac49f")] + [InlineData('y', "9d0f3db671f9fb22104b984763616732d383154a7a0dcdbb9ec17ab647b64961")] + [InlineData('z', "3b4aed1c401f71809c93e713f4b86fb6d56c5b668f4ad8b474cb8884756aac46")] + [InlineData('0', "f9e2eaaa42d9fe9e558a9b8ef1bf366f190aacaa83bad2641ee106e9041096e4")] + [InlineData('1', "67b176705b46206614219f47a05aee7ae6a3edbe850bbbe214c536b989aea4d2")] + [InlineData('2', "b1b1bd1ed240b1496c81ccf19ceccf2af6fd24fac10ae42023628abbe2687310")] + [InlineData('3', "1bf0b26eb2090599dd68cbb42c86a674cb07ab7adc103ad3ccdf521bb79056b9")] + [InlineData('4', "b410677b84ed73fac43fcf1abd933151dd417d932a0ef9b0260ecf8b7b72ecb9")] + [InlineData('5', "86bc56fc56af4c3cde021282f6b727ee9f90dd636e0b0c712a85d416c75e652d")] + [InlineData('6', "0c67354981e9068905680b57898ad4f04b993c63eb66aa3f19cdfdc71d88077e")] + [InlineData('7', "8f9b51ce624f01b0a40c9f68ba8bb0a2c06aa7f95d1ed27d6b1b5e1e99ee5e4d")] + [InlineData('8', "d14a329a1924592faf2d4ba6dc727d59af6afae983a0c208bf980237b63a5a6a")] + [InlineData('9', "7609430974b087595488c154bf5c079887ead0e8efd4055cd136fda96a5ccbf8")] + public void Sha3Hash256ShouldProduceExpectedResult(char character, string expected) + { + // Given + using HashAlgorithm algorithm = Sha3.CreateSha3Hash256(); + + // When + Hash hash = Hash.Compute(algorithm, [character]); + string actual = hash.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Sha3Hash384 should produce the expected result")] + [InlineData('A', "15000d20f59aa483b5eac0a1f33abe8e09dea1054d173d3e7443c68035b99240b50f7abdb9553baf220320384c6b1cd6")] + [InlineData('B', "8283d235852af9bbf7d81037b8b70aaba733a4433a4438f1b944c04c9e1d9d6d927e96d61b1fb7e7ecfcf2983ad816b5")] + [InlineData('C', "7b95dc4d4d327449e6b84bd769d053f190568504270b32789990ac7b75bef7fcfda2931d16cb5785b9ae61a15bbead55")] + [InlineData('D', "3ff600ef369ae191ec740e0119926f7e7b7621dbc0f4de818045b88e659230969894e1af894a4edd7a97812f5d20cc10")] + [InlineData('E', "8d479cadb1a83bd1864a636b1cefd7ac06f7c96940f022ac7732336e96a2cb27198153d314842182b79c063c4ae8f4a3")] + [InlineData('F', "01c126a5c70fa68dc33d3be695070b4d837e83caa3b76df066283361f4b942abd40510747f449c4e0d19861dc0a4d413")] + [InlineData('G', "224f9604e3b38a03e335b0a78f6710f36f4ad12e2c58289caba9ddac124bd0076c912fe02a787d4cfe1f29ff4ddb75b8")] + [InlineData('H', "1ebe9a1bc7ef3153626b1e4726aa6e28800ba39cec42491bb3b526f9b825a7ba7e22e24beaa4ab1b55b6e6a44520d1ba")] + [InlineData('I', "daf032833345d6ead75be31f8c713590530b5a1a6d7134cdcb8dfcf4eedb67fa124d6cfea0d2a02f68f986062b12dc5c")] + [InlineData('J', "4f6dace508a646b071eb60546aabe666829a8cf50a8d3c8e97888a2a1db5b12b8991e517e2331983f0fc99b6e0a92431")] + [InlineData('K', "5c61420db106b2cf478a04948ea59114c1a994c594fc923afacc04858715d69126f0089515872042dfbe6a8d5e062e4b")] + [InlineData('L', "cd3967f516705f3abbff77e35c8cfcfc6a8f915df60cc5a56ec51248580deedd6d043c364923285932ac00bc85fa6705")] + [InlineData('M', "55b0a1bb027524210861d27a5554e4c24d7b48da7373c98d398a760edc2a9c62ffa4d2b15c792ea93b5576ba2624e376")] + [InlineData('N', "c8894d0f096c9232ff7545833642c20061d6e93c75d558c020fdd92ff278336757ab14be364b2bfb306c1af4bd42a312")] + [InlineData('O', "3f0cb1cfa5db5e4741efa72c8c309f3669efe7ac6619a7528b5ff4f22da37403e9e68bce96aabd7b67cf387b548e608b")] + [InlineData('P', "04ac39f4be45e26b203fc712e1072801cf0f90dec53a26e1be1fb886340e6cb06375464f7150b58adcad215dccce732c")] + [InlineData('Q', "c66a74deabfeab86cdfd9fe16d8e20915087ae3b3627113bac0bd739822c07a609b45b29bca82501a6dc4aefe09def41")] + [InlineData('R', "3bd4e7dcad9d3c02adfa7aa5388727d346278a9a7b007f497b48a4fa2a12b9545c820df150854a8f8c494275bd6fd941")] + [InlineData('S', "bcc4f6d7426e832ccbdd03e30f6dc6b837c5f5780f8efd58122ab9086edb78d86b985e6b4dbd9f89d24486431dbc89be")] + [InlineData('T', "daf2c5c49a615b7ca9a92c85800f690788246809a23652f7b613fb231065cdf110a872dfc3e094b47be4a986e9a451e5")] + [InlineData('U', "351d1a799be78278a04f2e9128d992ff130251a9b88ab26a5525097c10e1209e60a2fbfc379a0ea983a46dac261ff469")] + [InlineData('V', "08e8ee1a3416fbcb0ca7d0d53556090c17f966de3a7dda5db0267aeb9088fa5486f9a425111c4c9d7a4227118ac4faf4")] + [InlineData('W', "653fac6cdf0fad1c202f71847e9360d18b0ab62b4e0279226eba96f70631747b3853624cf8160dbad575642563fec65b")] + [InlineData('X', "7b02671ba315c6c59b8ed4d1fa0aff47ce1c46b6ae534e9f3083d03bcd8af85f730a835daa1608da913478dcaae4caa3")] + [InlineData('Y', "17b15a22de43482d1a07c944812703b1b147928d23e8a4e9c117e8d7e6aa3132b65d50836eeb64969030bd150dea4d77")] + [InlineData('Z', "8bceb69fabf2bf9ffed6f132c037301870fcfc2de42fcb01df1f26ad808eca1b6077b37272dab03ebdc258f351ee1537")] + [InlineData('a', "1815f774f320491b48569efec794d249eeb59aae46d22bf77dafe25c5edc28d7ea44f93ee1234aa88f61c91912a4ccd9")] + [InlineData('b', "0c851fd986de48f9703a157327512d705e0aec5e339b53d99f4f3d55b02bd81a513e3ab059d20a348c993acd6591d347")] + [InlineData('c', "fc046ce484597913e61aac55245cc91c7393a9cd69012f22b389ab14ce40ec56f4520cdb1a2054ad3e588e192ec0df5c")] + [InlineData('d', "0312ab38cafbaa6fffe82ab1aeafcce1d4c656c5fde60444232a374df23d6c364c4f33bb044ae258e25111227c9d57da")] + [InlineData('e', "114681f5af3e1c7be7bfb31f60b1bab2de762d43258a23f56f92dececb14949956dc9bda8f248b62a881299064600b4a")] + [InlineData('f', "3f803d234b62ccd243b91510c620c15aaec715c7c46491fb640130322906cf8b52e0e129200459d04746892562cd70d4")] + [InlineData('g', "aea65684980ae4b2c328ccfc045cf27e8ede51c5ed11e85813f7e5709faa7ed3653df2333fa9310f521813a8cc5b80da")] + [InlineData('h', "906c31e68be36e29921029db158e0b4a6b083441e50a40bcca6460d5122bdd1c331cb6b867c9451f48e4745239a6219e")] + [InlineData('i', "a293952c9b39b0ad52e72686526ffb7981cfefa6a9a836b36f87d2f6409b0d41699eb4ad6391a5856978a0f601e43679")] + [InlineData('j', "42a8f1be481d8b95e919ca68bf684bf4476606dcdcbea2924289b6a10a8daa87fa89cdda0c252a77ef841bad5b258bf9")] + [InlineData('k', "b3311bb3e3415615a58fc9001704bf32dec9fb294735783e8195cd479979408e7c36d564934d64a5cea541f3f3bf2195")] + [InlineData('l', "d1a95dab99bdfc5e1f48213027c463387c617881903985572d43433b4e4d8d21e0906abb58c2e4a633cc16abba1a9663")] + [InlineData('m', "5428b66b2021a5090995a9f4964f8f82fb34712d4a10f69f1bfff92f8534e3939d86c83b441fb83bb937055733b9e6d9")] + [InlineData('n', "4303b4457f0cd358a24b43c1454327e2b2cdd56d8975fff4be77119dd8d27291a65d26a1e3233f3b773f6d82d2e78cd6")] + [InlineData('o', "e0133f6d5dd9727860f150073dd6ee154db4e440b65b7d26889e503039d54f5fbfc4646476cd34d808a0089310000dc5")] + [InlineData('p', "c441ea8b76d530b8a4e95e35f6f4eb0d8de7526b8d9972d7f45fb9f5301805c8b73d559e4c8458a001a1a1ad9b563dcc")] + [InlineData('q', "a73cf129eac67f6b9e2f3818b3b845572914c3c6821fafdc71d834f7852ba1c1d894c1a1d71669b9090d1a08418d34d9")] + [InlineData('r', "f01f898eceabaf8863678b738f224815a5746965e7eb1a91d4614f9eef2328791252037a1add0180f7f4f3e7fa66edda")] + [InlineData('s', "e5c105cc135ede693be4be4bb2c9b624a90fa1e422e43b97948ea6ca14f2ffff36b6f586c46110db208999f8a2f0d139")] + [InlineData('t', "63644c71a1fc2e1a2d1aaf429338b0e04e34738ef744f7c6d59ae9a9f96d096fa0852f20b4762c581e604d0178000da8")] + [InlineData('u', "bef30a27a058db0cf7397faa3eee6aad5736618be94a6ea284d2da411ee1f087af864d709d57c0827e647dc722093b69")] + [InlineData('v', "1e5d1e7b4777d1c827f77385016e0ffc832efce7ab2888808f34de90e44b21751e648b902a5dc3ceaf0c847a9727a047")] + [InlineData('w', "045ad9ad61b764222e1a1d8f442d1eb62434805d98e516e2394911949a08a3505629b9e3f2fd27ca25fedcb42bb8dc71")] + [InlineData('x', "5abfc7bc2a09a612f87987ce070634a0932d31891a61a0ec598e81e6ec616c9f00f05ff627070cbf6cb0499b1c334d4d")] + [InlineData('y', "40567ee6c5b13d88390bbec7b4364d1308960652a87ef83208e1bc23867b96638c5c2e3970a91de68a398ecb51452c90")] + [InlineData('z', "2b053962ede73a41a0235fd9e29243b2bbf3513a8b1d586525949fde2f38c659808ee0254dda75ee310185635e42e041")] + [InlineData('0', "17c0608360f9652153b4bf29611b146bbb7ed3336c33d944c8cf7637ffe8ff440b3b0b67a127a183a5d7e2d978f544c5")] + [InlineData('1', "f39de487a8aed2d19069ed7a7bcfc274e9f026bba97c8f059be6a2e5eed051d7ee437b93d80aa6163bf8039543b612dd")] + [InlineData('2', "39773563a8fc5c19ba80f0dc0f57bf49ba0e804abe8e68a1ed067252c30ef499d54ab4eb4e8f4cfa2cfac6c83798997e")] + [InlineData('3', "5f9714f2c47c4ee6af02e96db42b64a3750f5ec5f3541d1a1a6fd20d3632395c55439e208557e782f22a9714885b6e0c")] + [InlineData('4', "d87826dc897a66ee657458dbbe788e473e809b47c93bb37902b74b53999ae64a0ecdc8f76b28b608c2bf66f836d1b8d9")] + [InlineData('5', "d17e08f9fd1ec955b2384bba9312e525edad397e244071a0dd499c3403719434c5c21d833e7ecd46ed47f14d2bdbcfa3")] + [InlineData('6', "7cca6b41713794de552e96349b5f5bf35fa9f12806bfce76a5aa3cdd450e0a98495be64b2023f3188e80cbe27c802d1b")] + [InlineData('7', "4bf873ccb328cdc95a26473588df6c107706c166e240294fc5c70c2b220adc9314e166b0a77344825a34a835cb422ebb")] + [InlineData('8', "854ed8ecc48ed40a6bbf2fc0de3cfbd1811937e23340b245d2d618dc3d5349dbb0fea84e54184557247df6f456731040")] + [InlineData('9', "4894ec28d9d6494918765447867b8fbe65f7a6ec5a30f5aa3ce168c766fb8f9c63cb02602c730e8b259381942ac1f49b")] + public void Sha3Hash384ShouldProduceExpectedResult(char character, string expected) + { + // Given + using HashAlgorithm algorithm = Sha3.CreateSha3Hash384(); + + // When + Hash hash = Hash.Compute(algorithm, [character]); + string actual = hash.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Sha3Hash512 should produce the expected result")] + [InlineData('A', "f5f0eaa9ca3fd0c4e0d72a3471e4b71edaabe2d01c4b25e16715004ed91e663a1750707cc9f04430f19b995f4aba21b0ec878fc5c4eb838a18df5bf9fdc949df")] + [InlineData('B', "7b637bc5543d96f49500aaad3b27d8bd37624db23d415c4d0f3dd231e9b9fb061f39b7d8561c540650de8bef02aca43a2069cc2512697bd34f2244ee732743a9")] + [InlineData('C', "be0c2f5b07cb96d61f0e1e3fd250f0a1709d7388a24e192b9734ae0f9c92abcbd095fed6c5978ad9e55bb62a6a2ca16532eb3f3e5b3bc1e64209546e7e887445")] + [InlineData('D', "eb3eb4ccf7cb3db0ca62080b7ad8a255879c9aa1334a4a5f751687577e3f03b1afde16a38003b029d426b2dd74dfa0fa3cd561fbf79d86bf2c9f966ac154719a")] + [InlineData('E', "41b334d0a39eed4c28639643919433d8976248dd70fbb2b03ed2f233a8820a5de496686c6a81a3e1897ccd8794b92743b42617ab38152f2a8a04e588bad5742d")] + [InlineData('F', "b1845edee6f21b7b4ca587b3b22514972fa681f9380184a8e946a40c432239537b2558a774cd84c28488833fecc9567d57d3a99192983ac931b14f6b0aeda9b2")] + [InlineData('G', "b32657b8079a2eb23041a360c20b8b7fa4c76e300912ccf019ca2e94ec33c898a93b39fa8c1a6f1bba933db63e1a027bf52ee6d23e81aac71ebb2721031a7881")] + [InlineData('H', "8e844c36dda15c37458d23c88a6e66782a5ac90cd0135960b658f4d3e3c783fc2bbf68a0a8e2a054d7d52f9b1f5417bdf4f0e2825fcceb0fe0375466426c1f4c")] + [InlineData('I', "6b8b537691c9252e34bab51bf067ad765065c97f6dfd2c346c8b9f020698187826ed2be1f1669db72a476453341fb0c7cdda49bbf6ec5b55899bf0b64c3e09e1")] + [InlineData('J', "5a3f7519955a950ffb0f9f839649f8a88a20ba2c746da1fef8d97a5c4d9e4b0a2fbd5a8b63ee74a6322a1d0bc3d447717291f3dc0c504f38b4a7ca5998961253")] + [InlineData('K', "afd0107aaf7b3ed73353cf54ca923d2c1f8e75c151a19bf8d2e0b7f873db9b5ce33e6a1db692dcb352fba4b89b1a1ee823f19abd1485e8018f9c71e64bacfd8b")] + [InlineData('L', "6bbac080a582f03fa999fb1cc16a1d856191bd84dbaea946312e980c2ddf5e61bf754b5028f93191d8ff237d6030634001dc8799651062d1a96e44e210599c02")] + [InlineData('M', "e3c3b7d964d08646d4935b2299fd02d79db5b2132059cbf3cef72066871b85812ab2489182c5fbffedadd67f89cccf08b7b744a4c8ff050117a9b9068f508002")] + [InlineData('N', "471126be6139191b7c622abbf162fafaaaa2b46caf5ae11787b2d70d9c96628655a6870e58eaee4218864c136ee5d24e81b39000cefce12fbd407924cafa36e2")] + [InlineData('O', "3d75f1a138ee6317875acc325062b5d4bda8af7a715f372d6bc0e618d8a64feaf462b833471846770cf8648c28a09fc24a97574e52c8a3219e59e2d5048dfeb9")] + [InlineData('P', "4dec0e71e1250d9edcca403f02023fcbbd88be4d0af99a4dc4494ab4505ec07e0660804af0c53c513f1f3e2981ab4d9f7325c37a6cc075ff5a0f438666767030")] + [InlineData('Q', "e95b1fd29022cc854c5c7cf4d4704de993ac8d093bfee5b0c6ede93af431458e8e19c31934125aff62984f574ce3a30f6251a7ac11381e92b4a1f52283e13a07")] + [InlineData('R', "8e48ecc4d3b8a5125db648907fe0ef8ec14b353302779a5c6a7fd8a8142ab97a079602a51f02fdff0bf28dbae03212cfd1538901689f8c90c7425ddac7752d5a")] + [InlineData('S', "329fadd7c1d5f243d57af8a95da82235d2b846681d725e9eaf7095800fa66197144044622c79b37b9e501966e6a35a866ebf03d0b3033e446b993d3f5b193de3")] + [InlineData('T', "7282ac39a48e7cbba327dabc6843ba412970d9ade37e49c5ce8f0360d61a6bc4644a3b9947efa013d8429cac9ca02dd28c1132236c09aca9e57910e3a1a8046f")] + [InlineData('U', "c581306f35e63725c488de906569ed6675e577eab4f75cb1c06b19164c7efa47899d36a365cf228f9b7688820ed0df2b2a4f72a0fadf03a6b2cf3e75440cb6a9")] + [InlineData('V', "6b212db1ff14f2781c78334afc9d9b8d57a2318856823ec7fa78ee3d39b28ce29e8915f4fceab367c44b52acfed0989945e5d7537f9f89553fe47e443d786be5")] + [InlineData('W', "cac54800b600476ec1132e9c58b486bb92ec9bcc4eb3c52ef7bb97ea42eac8b08ea047b605eb9d146b273720c37649b9497bc77f8dee1d327fdeebcbf06729bb")] + [InlineData('X', "c1d414ec5914ecbaa2507f89fe9eaee9eba8ba506bf1e58faf8c7982d4e0329fa8824f7ee8f0258f0b23a304d93997357c4c732d5bdb1288fe7b1af68ba97432")] + [InlineData('Y', "c66a0c202ae9466c93deb74b21c15cf6bc789e5e88b0327486b5476a1aed0e9a2053b549134d041447156aaf4bd1944862d820873873228f52fba106a059c41e")] + [InlineData('Z', "fda430c40ee744a4f06e6a750564e16e80451b1943dbd11f8f8f399b1101a06d723c1f730cc8d996f7b5ba5656c6b963dab711dbaf0eb493978db715ee4ac986")] + [InlineData('a', "697f2d856172cb8309d6b8b97dac4de344b549d4dee61edfb4962d8698b7fa803f4f93ff24393586e28b5b957ac3d1d369420ce53332712f997bd336d09ab02a")] + [InlineData('b', "8446c46ee03793ba6e5813ba0db4480008926dd1d19efe2c8eb92f9034da974d2171ae483f29ce3a79ed4fdd621ae1ed14fe12532af95ddd0728779ce5aa842d")] + [InlineData('c', "bfe4d7f7377116dc15f794d902621797b72b32396382de2b6e49d4f1d7eabdfddcfc3bc127bb67f92f9458a5733bb21804e7ccd56b4b6f81049339f477cd279d")] + [InlineData('d', "4668897682ccd2b1ee0cae8dc55947291f819cc59ee126f5bd243b1852577414413aeed5780b5fb11090038715beed1b00714a15b31c8d9674fbdbdf7fd4191c")] + [InlineData('e', "6ebb8a73bfd0459bd575b9dbef6dcb970bb11182591f5ecd7c8c0d771b3269b715fcb84005d542ff74306565a46b3b893f64ca41b8519457ae137f6429dfbb1e")] + [InlineData('f', "10a090626438fdee4f1244562d6a39c56e515dbf70293584c5a20ed2e8e048905ce30af923921276360817aac682ad30f462033d97c00670edeee8281939a60c")] + [InlineData('g', "2ca04c154f94c314a835993acedc2634cb2dc491673b2cafa8906a5a29bfc3eeac19fc4baef80932c46184e0fd458594ab9e7e020ce70a25db393de171d69840")] + [InlineData('h', "26cfb46b8264aa515069b0726c0ed4d1c08587a2f1572fcee6a06b6611ba7802e657791c8e64bf372042bd86208995a9a2a1ef2248d1202137ae65b0906f1ae3")] + [InlineData('i', "baeb91abb764a812dcff52b66a8a92747c07c4ecf08140b73b0e3819abd35cb0634062ca992e74a65bad3c02fc3dc6bac2bd60bc4441771df9ea095842738c39")] + [InlineData('j', "998e8fc13f2160c6dfef0bace960efc019bf173addd5aa3a1dcab50ec8e0d66637b30d0c37f88b09e57477b87b5ddd88b424191ff8e757b384cea28801fe172a")] + [InlineData('k', "8771111f7c5b23494cde7bd3edb03a31e0363d7f76d8ceb07a1300164cf1ef2252e0fcb9e404f6d88785ca2a59f0379d277f4dc7b16f76a726478a639b2da8ce")] + [InlineData('l', "37e275b9f5a7067372be037c5d010e04d3d3ab0df5aab129a9379d9b9c27ecef3f7fa7bffab6582c18323df04c9d0c53cb63fdd5dde484f4227eb60f184756fd")] + [InlineData('m', "7c8e9b49719fda980d594727bd9d3ce693349bba9b303a492726ed7107551879be951f959c55e11b6b1fbd24668f5ee83339da547c04ebc13b56df8b12a03cc0")] + [InlineData('n', "10f12efa3c8edddb5343f970ce1a9037d02764e24e0dceff59f9f66afb3e69158f5ea6666f99f4ad33c47ab9e0c93a25032fd24f1aea6d64ad6b61f7a6dae9bf")] + [InlineData('o', "bb4e922d85066e5ef0a215d59faade03f55728f59a552fc742065d41f189e17dea56a9338764f84bd714f043c2da71d157712921b69a4f23adaebd9366878371")] + [InlineData('p', "9a768ace36ff3d1771d5c145a544de3d68343b2e76093cb7b2a8ea89ac7f1a20c852e6fc1d71275b43abffefac381c5b906f55c3bcff4225353d02f1d3498758")] + [InlineData('q', "f435ba3ef2bf43e694c8940fa315641c67f152c2ee2021f121af5e03f9860607f74e61e1451f9489c2ff59f87dc0e1c501566e2324355de32770ec52cc3bce47")] + [InlineData('r', "d4683a427e18f18bdb592e45c8202bb4f954af961cff43131c358c53980e7936e0e2d2da7fd1babdafddebf8f0ed0ec285637f9fe292241c620633d5524e5122")] + [InlineData('s', "723a86b292df5e128ff2d1945391b8d9f4bb17de3c13f9b8527b1f49fffa2ec69b91b137294aa6b69b78349e20ec17520c338cf33968f86b9383a33d6b0716fc")] + [InlineData('t', "28f9769820918857e4ae2b4e91a41d8624d58fd926f7c3678732d69740c5684db562accf252cb8cd06bc4965186f9d6d5c5c5235c2ebede586d6526bcb3fcd92")] + [InlineData('u', "bb5458b8d4376d42b1f4c18308c8d8a0fe4cf2b97007b6f55d928c41fc19bbf18c47565e0e5ba9ce26612e7327d947769f191cbfc1d542ddd0c05b3c73e4f173")] + [InlineData('v', "b9a3ad42faec4820b964d8027ce03d6a0a73f9a926cf543002c59ec1e2d385060ec71884faaacbc66e651c9e7a8194add6d1467df0419e841a4cbde075cb0182")] + [InlineData('w', "35f8e0298f058a564e4b23e3c45c9a42f5a1e8757bd4be0a0ed40fcdff2bb2e78dfa57bf37267fa619766a61c4842e7b403122350b8195a2990af602cb4226f1")] + [InlineData('x', "0fdb27960308c51467edd49a0f5e0c434c9cca721f4c35bff005feabaf6010e777a1137ee8187c5288af57578d18d502a0bbe4c022f5587541961e10132d9834")] + [InlineData('y', "ab2962a6563627545935edbb63499e632694f0e8766ac52518e58cb1c1289591729d4a6f92636684ba601b56274d715f17ed4885b05a743f38b27aabdfef602f")] + [InlineData('z', "ffe4d7127d5e222ac77ded78b503276294960867d5501eda748bbb741dbc238d1d68f5f4c76f38fdb03a491bd9ec8c1e20403440315ac5e8050946a00409a724")] + [InlineData('0', "2d44da53f305ab94b6365837b9803627ab098c41a6013694f9b468bccb9c13e95b3900365eb58924de7158a54467e984efcfdabdbcc9af9a940d49c51455b04c")] + [InlineData('1', "ca2c70bc13298c5109ee0cb342d014906e6365249005fd4beee6f01aee44edb531231e98b50bf6810de6cf687882b09320fdd5f6375d1f2debd966fbf8d03efa")] + [InlineData('2', "564e1971233e098c26d412f2d4e652742355e616fed8ba88fc9750f869aac1c29cb944175c374a7b6769989aa7a4216198ee12f53bf7827850dfe28540587a97")] + [InlineData('3', "73fb266a903f956a9034d52c2d2793c37fddc32077898f5d871173da1d646fb80bbc21a0522390b75d3bcc88bd78960bdb73be323ad5fc5b3a16089992957d3a")] + [InlineData('4', "37f558134baa535903c6a88931c8122e334368bf951f2cada569b11774ef9795ef6d2ac961d13ee44a0c837db3817bb9db68ac3bdfb8b19a1308618484a9da8f")] + [InlineData('5', "c74bd95b8555275277d4e941c73985b4bcd923b36fcce75968ebb3c5a8d2b1ac411cfae4c2d473bff59a2b7b5ea220f0ac7bb8c880afb32f1b4881d59cc60d85")] + [InlineData('6', "503ad3364d41a2362f28136ee8a9615108277986f52c34ca170b664eb1c663f5e407e9a3084e90017e315b24ba9162021c477e29b3bb1f84a37eea841fe12b9a")] + [InlineData('7', "72ce921155976b88a4a4bf39a4127c4d9e272eccde35ee864963da855f32330c0f8075aafc3a3aadecf498ee7b5e2f9ee3529ea46d97ee0795bd548b41463771")] + [InlineData('8', "f30e8484fa863883156c517514c4e2a9096ec6009f40ebfb9f00666ec58e52e50e64f9074c9182a325a21cc99516b155560f8c48be28f11f2ee73f6945ff7563")] + [InlineData('9', "b55cf27ef01025e3c761a579a63d1c7c1e54e2d12f8f2928c90f5f5516b0d9c71f2fac9e7ccf28c5adf33c3f78d9548ebfed2dc46dea944aed336d1650721487")] + public void Sha3Hash512ShouldProduceExpectedResult(char character, string expected) + { + // Given + using HashAlgorithm algorithm = Sha3.CreateSha3Hash512(); + + // When + Hash hash = Hash.Compute(algorithm, [character]); + string actual = hash.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Sha3Shake128 should produce the expected result")] + [InlineData('A', 16, "a5ba3aeee1525b4ae5439e54cd711f14")] + [InlineData('A', 32, "a5ba3aeee1525b4ae5439e54cd711f14850251e02c5999a53f61374c0ae089ef")] + [InlineData('B', 16, "74865dbf56f0d9c27b76300b1872ba5f")] + [InlineData('B', 32, "74865dbf56f0d9c27b76300b1872ba5f852c2419010ac745bcabf4500db91fc2")] + [InlineData('C', 16, "2e9587f4196d40eccfc86540d53c34f2")] + [InlineData('C', 32, "2e9587f4196d40eccfc86540d53c34f2282cbbdac7e17c873594d93fb849b2b3")] + [InlineData('D', 16, "f0695584e963aa0f01ac26526ffd4061")] + [InlineData('D', 32, "f0695584e963aa0f01ac26526ffd40614d8920fd947503de8155a6f78c7d4449")] + [InlineData('E', 16, "9e677faf367b255042d0ff421c11a097")] + [InlineData('E', 32, "9e677faf367b255042d0ff421c11a097e5f444ebae4051b698c077e1969224ca")] + [InlineData('F', 16, "a2c949bf7c27b871cbca13f0949f9f2d")] + [InlineData('F', 32, "a2c949bf7c27b871cbca13f0949f9f2da9a234f53bda26f7b220ebcf69963870")] + [InlineData('G', 16, "81ca32e51bc34a70ae1a52d1517e1a6a")] + [InlineData('G', 32, "81ca32e51bc34a70ae1a52d1517e1a6a8c895e43bb772ff39e82d079133ab1bd")] + [InlineData('H', 16, "db72f8cc2e23e24e6485137fed6e6dd6")] + [InlineData('H', 32, "db72f8cc2e23e24e6485137fed6e6dd6f5474d929fd5b20a8708c35d5638ba02")] + [InlineData('I', 16, "9264d43898745dcfaf194719f2f4edaf")] + [InlineData('I', 32, "9264d43898745dcfaf194719f2f4edaf3145bd35a7be80187e3b7fec30486ce2")] + [InlineData('J', 16, "5efe2fbaa173fe4a8492e96089f066dc")] + [InlineData('J', 32, "5efe2fbaa173fe4a8492e96089f066dc55d04f038a012363513c6f924e74a7db")] + [InlineData('K', 16, "58a8694c7e0364217702e964eeaf927b")] + [InlineData('K', 32, "58a8694c7e0364217702e964eeaf927b0da95486164f928a607e39561e138dec")] + [InlineData('L', 16, "73706247bac5dbc741be1ad46f3e62f0")] + [InlineData('L', 32, "73706247bac5dbc741be1ad46f3e62f0fb834b6403a62448c672b074ef725065")] + [InlineData('M', 16, "b969a39b683ce8f8e80ac2c08ce116c4")] + [InlineData('M', 32, "b969a39b683ce8f8e80ac2c08ce116c4c6539100b715c2e01a1dc18bcee9e6cd")] + [InlineData('N', 16, "9e1bfdaba56285939e655aba57b078f7")] + [InlineData('N', 32, "9e1bfdaba56285939e655aba57b078f72ddd0bdece0a73c928d61c998ac4569a")] + [InlineData('O', 16, "4ac61591f84dcb84913e5f6be341f100")] + [InlineData('O', 32, "4ac61591f84dcb84913e5f6be341f100dd7b99f606e21a449ba7f7236f65ec09")] + [InlineData('P', 16, "eab4480497429cd15b8bfdb46014d85f")] + [InlineData('P', 32, "eab4480497429cd15b8bfdb46014d85f89b2621a6785d87dc6e1d160354478e6")] + [InlineData('Q', 16, "bd3d67b5dbf85163d78b6cf16df8c94f")] + [InlineData('Q', 32, "bd3d67b5dbf85163d78b6cf16df8c94f5fba33667d77cdea00476314633b50bb")] + [InlineData('R', 16, "613edcc87e371533095dfaf67754de88")] + [InlineData('R', 32, "613edcc87e371533095dfaf67754de886a38f321d418d069b06af1d63ea29d59")] + [InlineData('S', 16, "9934d41dbceac03b9795ef28330708f0")] + [InlineData('S', 32, "9934d41dbceac03b9795ef28330708f0b494b36786222d6dd148d54193c7e217")] + [InlineData('T', 16, "9dd7847b4c29404da0cbaa5d1cb69df4")] + [InlineData('T', 32, "9dd7847b4c29404da0cbaa5d1cb69df451878f576d2c4bef29544ee025367484")] + [InlineData('U', 16, "286668ef63f9546f20767908cf44d5d7")] + [InlineData('U', 32, "286668ef63f9546f20767908cf44d5d77c0fef4c680aa3f61660ae3beac3aacf")] + [InlineData('V', 16, "55360b718e1ed3de9ce9ce7a08361c91")] + [InlineData('V', 32, "55360b718e1ed3de9ce9ce7a08361c916e8c5d0529f0a9f627eb23e2ca3db8d2")] + [InlineData('W', 16, "c4abaca1f7f8691f4623cac449557dfb")] + [InlineData('W', 32, "c4abaca1f7f8691f4623cac449557dfbede55e269c6e0904b01b921d8a2e2dbb")] + [InlineData('X', 16, "a378c3f63abcc74f0ca75f3b5d0ef6f1")] + [InlineData('X', 32, "a378c3f63abcc74f0ca75f3b5d0ef6f112d2fa716edf851d0895f7bef485ee0f")] + [InlineData('Y', 16, "5bf27867460bbc4a67d5f3930078d748")] + [InlineData('Y', 32, "5bf27867460bbc4a67d5f3930078d74831f08d66190c348b77f0da15b1bafb4f")] + [InlineData('Z', 16, "dad14f5a3d2237fd294fb618e14eae83")] + [InlineData('Z', 32, "dad14f5a3d2237fd294fb618e14eae832c0ee3b6c12dd850cb0196c36dc1c204")] + [InlineData('a', 16, "85c8de88d28866bf0868090b3961162b")] + [InlineData('a', 32, "85c8de88d28866bf0868090b3961162bf82392f690d9e4730910f4af7c6ab3ee")] + [InlineData('b', 16, "f0ffa34335ef979fcf79a200874749da")] + [InlineData('b', 32, "f0ffa34335ef979fcf79a200874749da3054fe398bb6d2137d3c98b82df9160f")] + [InlineData('c', 16, "a5c1009bf9fce98b7930ae5fe7aa7ca0")] + [InlineData('c', 32, "a5c1009bf9fce98b7930ae5fe7aa7ca06c7689fe2bd9be8a75373f1a8ffae454")] + [InlineData('d', 16, "5943bb0f0a00c1990d9a1057656bd983")] + [InlineData('d', 32, "5943bb0f0a00c1990d9a1057656bd983b8fbf44363127d15848d3ba54c3561b1")] + [InlineData('e', 16, "bb2b536f0606a0910bf4b98c74c75e96")] + [InlineData('e', 32, "bb2b536f0606a0910bf4b98c74c75e966d0fbcd792ca55e3c768ca2e92234d50")] + [InlineData('f', 16, "2c6c3bcd720350d73d4f46724c098901")] + [InlineData('f', 32, "2c6c3bcd720350d73d4f46724c098901a788d00e2c25ed9d6b789af2c9dc0982")] + [InlineData('g', 16, "7a529e89a30f8e715331b98032cbda63")] + [InlineData('g', 32, "7a529e89a30f8e715331b98032cbda633e3625c51414cbfa8843a568bd39374c")] + [InlineData('h', 16, "ed6dba4b983e0e45039b17d4ff85c81f")] + [InlineData('h', 32, "ed6dba4b983e0e45039b17d4ff85c81f9a829797def86339dec4b4d0f596625c")] + [InlineData('i', 16, "78ac692a457de231fd8e5bda490a1d0f")] + [InlineData('i', 32, "78ac692a457de231fd8e5bda490a1d0fdb6d1274d505385ae196d821fbd2aa51")] + [InlineData('j', 16, "60e284f4daedb9f6afcd8fe698f7dc7f")] + [InlineData('j', 32, "60e284f4daedb9f6afcd8fe698f7dc7fffa8503cb41d4a83709bbbbd449aa843")] + [InlineData('k', 16, "ac20c8330b5c6c163747281430fa7a9c")] + [InlineData('k', 32, "ac20c8330b5c6c163747281430fa7a9c549ca49ee7d675dbb4511b1cd411a615")] + [InlineData('l', 16, "5238d98fc5871541974a81275dd5f1ea")] + [InlineData('l', 32, "5238d98fc5871541974a81275dd5f1eae54c57ebb0393fae9c6fa78accfc09d6")] + [InlineData('m', 16, "c5c955987cf895c48f31a150f56f57b6")] + [InlineData('m', 32, "c5c955987cf895c48f31a150f56f57b61c793fdca932fe909ad487bbdc3dc66a")] + [InlineData('n', 16, "68f8ea7d3b0bd13eb9d7f9c131dccbba")] + [InlineData('n', 32, "68f8ea7d3b0bd13eb9d7f9c131dccbbac2dc89940edc3d70201fded5363d3e44")] + [InlineData('o', 16, "a0b20673d0b9a9642857aed7faf41ed2")] + [InlineData('o', 32, "a0b20673d0b9a9642857aed7faf41ed2c739c5f23ac9e946281c23fd7f88fb5f")] + [InlineData('p', 16, "f884289b7f8c5ab613344841267a9a7b")] + [InlineData('p', 32, "f884289b7f8c5ab613344841267a9a7b2a79b0a0fee49aa0affd2aa4fe1f1643")] + [InlineData('q', 16, "87b8d13b05e63515cb6ee34685ece7c3")] + [InlineData('q', 32, "87b8d13b05e63515cb6ee34685ece7c3be88a65f5b68949a523b0cd68855e716")] + [InlineData('r', 16, "95434212048c97e0a06af33459defb3f")] + [InlineData('r', 32, "95434212048c97e0a06af33459defb3f9cbd95e2fcc0c7f9d572229687ce1dce")] + [InlineData('s', 16, "bc5ac4a37d609be474d3121af546e217")] + [InlineData('s', 32, "bc5ac4a37d609be474d3121af546e2177ef9af4f1ad2a0f5ef26d25de1e27b30")] + [InlineData('t', 16, "ef012cb5d92b651014fa6d9c3118eca5")] + [InlineData('t', 32, "ef012cb5d92b651014fa6d9c3118eca56a41f923e94b7242d1fd743e0c7fb9cf")] + [InlineData('u', 16, "4aed09875d70273d35cc94d52d25d4f0")] + [InlineData('u', 32, "4aed09875d70273d35cc94d52d25d4f0c3ad2c0a8d0d2d4dca4d117834995a1a")] + [InlineData('v', 16, "904f2f17cfe7bd45d5be9da1f931f7f8")] + [InlineData('v', 32, "904f2f17cfe7bd45d5be9da1f931f7f817c98f28f448109840ff585fcc5c3f48")] + [InlineData('w', 16, "1e332829e1b27a670aee5b0c0495b229")] + [InlineData('w', 32, "1e332829e1b27a670aee5b0c0495b2293e0e2d80c012cb9f8afac446c03dcc92")] + [InlineData('x', 16, "e472c5e394f30ff8d5d33803f9593e63")] + [InlineData('x', 32, "e472c5e394f30ff8d5d33803f9593e63e2f3862d48a41ef841e4d6486af49972")] + [InlineData('y', 16, "4cccd98df122b0736a05ea30c361846c")] + [InlineData('y', 32, "4cccd98df122b0736a05ea30c361846c5cb89596679b680d08e58a1c19744913")] + [InlineData('z', 16, "bb66897ef6ac6cbc29c3b14c6f1027f6")] + [InlineData('z', 32, "bb66897ef6ac6cbc29c3b14c6f1027f6f660b290bae53b4592848c3ed2e87885")] + [InlineData('0', 16, "628e79cf7948cd1ca156cee7631a3446")] + [InlineData('0', 32, "628e79cf7948cd1ca156cee7631a3446bc21d4947e0be55c803a0d5c40380b4b")] + [InlineData('1', 16, "ebaf5ccd6f37291d34bade1bbff539e7")] + [InlineData('1', 32, "ebaf5ccd6f37291d34bade1bbff539e76c47afb293c5d53914d492e0bdc24045")] + [InlineData('2', 16, "4e9e3870a3187c0b898817f12c0aaeb7")] + [InlineData('2', 32, "4e9e3870a3187c0b898817f12c0aaeb7b664894185f7955e9b2d5e44b154ead0")] + [InlineData('3', 16, "0a7fddc22e37eaf05b744459f6129fd1")] + [InlineData('3', 32, "0a7fddc22e37eaf05b744459f6129fd1c97cb501aaf497ecb6d5d9b1cfadcbf5")] + [InlineData('4', 16, "f7275a1ebcf0a3d7fc46e235dc236a3d")] + [InlineData('4', 32, "f7275a1ebcf0a3d7fc46e235dc236a3d678ea7c47b642b8aec1d0855d6bc7e4e")] + [InlineData('5', 16, "b485d77fdc221ecb320201c4cd09ee31")] + [InlineData('5', 32, "b485d77fdc221ecb320201c4cd09ee3146aaccb460a998c1b803ab4186ecdd43")] + [InlineData('6', 16, "21d93093fe84db44c4d2769ff7e4f2b5")] + [InlineData('6', 32, "21d93093fe84db44c4d2769ff7e4f2b5dc920dcc58ff7f390cdd4642ef7049d5")] + [InlineData('7', 16, "f99079a8eac6f051fac4e62b17f6bc86")] + [InlineData('7', 32, "f99079a8eac6f051fac4e62b17f6bc86ff0ab03eec648e776cf65781fd9fe997")] + [InlineData('8', 16, "cac75ec753ceb7fcf9e9a9a6d84236c1")] + [InlineData('8', 32, "cac75ec753ceb7fcf9e9a9a6d84236c1d39b8a013bd48e547c5a7409fc9eef3c")] + [InlineData('9', 16, "d8ef0690db21f1f2975bb5a860f7c46b")] + [InlineData('9', 32, "d8ef0690db21f1f2975bb5a860f7c46b92e8383520b71d485cc37b267c247ca1")] + public void Sha3Shake128ShouldProduceExpectedResult(char character, int length, string expected) + { + // Given + using HashAlgorithm algorithm = Sha3.CreateSha3Shake128(length); + + // When + Hash hash = Hash.Compute(algorithm, [character]); + string actual = hash.ToString(); + + // Then + Assert.Equal(expected, actual); + } + + [Theory(DisplayName = "Sha3Shake256 should produce the expected result")] + [InlineData('A', 16, "5e6812c0bbaaee6440dcc8b81ca68096")] + [InlineData('A', 32, "5e6812c0bbaaee6440dcc8b81ca6809645f7512e06cf5acb57bd16dc3a2bfc57")] + [InlineData('B', 16, "9b4033bf5151724308b4b1fc90f15346")] + [InlineData('B', 32, "9b4033bf5151724308b4b1fc90f1534688ea1a17c911aa3a897d5b6a05db5c25")] + [InlineData('C', 16, "6c1fcc1b777f8c560a5c6ac7a21d5d4a")] + [InlineData('C', 32, "6c1fcc1b777f8c560a5c6ac7a21d5d4a73e6948eae9c7c7b93bc5e2085564999")] + [InlineData('D', 16, "7bb2dce81e4f414e23454084c1c11d94")] + [InlineData('D', 32, "7bb2dce81e4f414e23454084c1c11d948cafdf5e85932618ceae8b3f9953c51c")] + [InlineData('E', 16, "4f78bc55b48ab68d5c7c5e91f7a9959d")] + [InlineData('E', 32, "4f78bc55b48ab68d5c7c5e91f7a9959d4b6748f1580382fe6e2170a6c0dbd691")] + [InlineData('F', 16, "ba84a59142ae7d8a245819b992152e95")] + [InlineData('F', 32, "ba84a59142ae7d8a245819b992152e95e167316c74e0cfb6867bf7177f6030a6")] + [InlineData('G', 16, "a01dc253b94528539c20cf5dfefcab12")] + [InlineData('G', 32, "a01dc253b94528539c20cf5dfefcab121de3524f701183a1e830e898705dd7a3")] + [InlineData('H', 16, "fd3d47ec252afaf37ee08bdd346a40bf")] + [InlineData('H', 32, "fd3d47ec252afaf37ee08bdd346a40bf768c1cb68432d01729b91c1c71b5d42e")] + [InlineData('I', 16, "ab44b02fab0fb7917eda9e709efeb696")] + [InlineData('I', 32, "ab44b02fab0fb7917eda9e709efeb6964172fcba345c6fe73ed6219bf77269fb")] + [InlineData('J', 16, "0bc8dcd68d6402c2ae942cf13d968229")] + [InlineData('J', 32, "0bc8dcd68d6402c2ae942cf13d968229e28574a5f94110cd22b97afc373f26bd")] + [InlineData('K', 16, "fba4254262cb96830ca70a363097888a")] + [InlineData('K', 32, "fba4254262cb96830ca70a363097888a21cfe0fcc0668d7a4952a621bb619f6b")] + [InlineData('L', 16, "becd3c8f9f288f6728f3bea68a80a026")] + [InlineData('L', 32, "becd3c8f9f288f6728f3bea68a80a02630e387551bc9530ee1548e37a55f6fd5")] + [InlineData('M', 16, "38613aed74157de1524d2b24f8ebda7f")] + [InlineData('M', 32, "38613aed74157de1524d2b24f8ebda7fa0890b869d50625c4f5512f957efa5da")] + [InlineData('N', 16, "5284ac45c58ae1800442c5d43d067e13")] + [InlineData('N', 32, "5284ac45c58ae1800442c5d43d067e134bd6bbf40c671343a553739d42cf7d22")] + [InlineData('O', 16, "4d9223d5444c05e92d9d0abd37d5020c")] + [InlineData('O', 32, "4d9223d5444c05e92d9d0abd37d5020cb41f10f4a27392c2facc124135b7fdcc")] + [InlineData('P', 16, "f1654d7130e8d85fca768dd011bd5348")] + [InlineData('P', 32, "f1654d7130e8d85fca768dd011bd5348f491e6903576c8e478b9fbe8b86322b2")] + [InlineData('Q', 16, "b64d0e68e2d381fac86172d12f1343b2")] + [InlineData('Q', 32, "b64d0e68e2d381fac86172d12f1343b20fcda532d59daf77eb44c5fc5943f4d7")] + [InlineData('R', 16, "4f6bf07cd877ad550fa2aec9ab3a10af")] + [InlineData('R', 32, "4f6bf07cd877ad550fa2aec9ab3a10af827e9285551c3d4009ceaeb3f9db7699")] + [InlineData('S', 16, "c5c21f9a333d36e7a9f5926e2e4a9883")] + [InlineData('S', 32, "c5c21f9a333d36e7a9f5926e2e4a988386c13126a454cce340b5c3a513a87ad1")] + [InlineData('T', 16, "a695c007e9bba6a81ed1ca7cbb853ecc")] + [InlineData('T', 32, "a695c007e9bba6a81ed1ca7cbb853ecc66415e06ee027550f26ef287ce51f839")] + [InlineData('U', 16, "85ce175af72e5877f858a1307089c207")] + [InlineData('U', 32, "85ce175af72e5877f858a1307089c2074cb5b6573d08f76ed7169bc52b2d1a75")] + [InlineData('V', 16, "0621c3c0c6dbb3d2c4daa2c4d5c66c02")] + [InlineData('V', 32, "0621c3c0c6dbb3d2c4daa2c4d5c66c026d2eabcbbbc55fcf811e77a3b306e7ff")] + [InlineData('W', 16, "77e786c411f0de5be44de0e4b034bbae")] + [InlineData('W', 32, "77e786c411f0de5be44de0e4b034bbaec33a2c31e372847e342f92a0ae2a6fdc")] + [InlineData('X', 16, "5404f315ad1550324f15a8ca77b41d77")] + [InlineData('X', 32, "5404f315ad1550324f15a8ca77b41d7794c0878ec1ef8c3bd800710d47f384f6")] + [InlineData('Y', 16, "cd7b48e3d243c0912de0cca30e7980ae")] + [InlineData('Y', 32, "cd7b48e3d243c0912de0cca30e7980aeedb188bc957aff0ccefd43f663ba2a73")] + [InlineData('Z', 16, "fd48054304d155cff97a6e1c4a531872")] + [InlineData('Z', 32, "fd48054304d155cff97a6e1c4a531872e99c456174bce19a660fdeb025a5427c")] + [InlineData('a', 16, "867e2cb04f5a04dcbd592501a5e8fe9c")] + [InlineData('a', 32, "867e2cb04f5a04dcbd592501a5e8fe9ceaafca50255626ca736c138042530ba4")] + [InlineData('b', 16, "e5796351f59c6264ac1866da170b79de")] + [InlineData('b', 32, "e5796351f59c6264ac1866da170b79de04cecb6317de6b05ca08e42abf32c785")] + [InlineData('c', 16, "b0f080246a623d2588fd6a8427575287")] + [InlineData('c', 32, "b0f080246a623d2588fd6a8427575287703ae4a8451e043d995f1e8f0afc3bd7")] + [InlineData('d', 16, "0142aad0876d139fe243d071563a634d")] + [InlineData('d', 32, "0142aad0876d139fe243d071563a634d56d2e3e1d15a8edf51f16b98d26467d2")] + [InlineData('e', 16, "24e123d7538cf7a23c8f8e6ed94b7e0f")] + [InlineData('e', 32, "24e123d7538cf7a23c8f8e6ed94b7e0f8edaf7aa4a10957583373c341fd4d1e3")] + [InlineData('f', 16, "b967c7cc5249454c318a7fbbbaaeaf36")] + [InlineData('f', 32, "b967c7cc5249454c318a7fbbbaaeaf36309a492e53ab1f604a9ac59cdfb57b52")] + [InlineData('g', 16, "10673dc5dbe94c1db4b4d5f909a954ed")] + [InlineData('g', 32, "10673dc5dbe94c1db4b4d5f909a954eddf17f22a6e05e66724dab315b3e5a84c")] + [InlineData('h', 16, "f877e016a2c3167ca3df83e5346d1b06")] + [InlineData('h', 32, "f877e016a2c3167ca3df83e5346d1b061a0bec1055ce45b729b181fc41bba729")] + [InlineData('i', 16, "3bb3af4ee58cbc3fc615b29774342549")] + [InlineData('i', 32, "3bb3af4ee58cbc3fc615b297743425497be0843a96a20a4a2b69d201c025eaf0")] + [InlineData('j', 16, "cb085dbb162ea9c3f2be3025c861c322")] + [InlineData('j', 32, "cb085dbb162ea9c3f2be3025c861c3222c98e59cb78e4d083a8bab80b0174bb5")] + [InlineData('k', 16, "fb7e1de572ddc648221bb7f112e43fb4")] + [InlineData('k', 32, "fb7e1de572ddc648221bb7f112e43fb4bdd0c11d7927816b70019e18c5209f0b")] + [InlineData('l', 16, "b29190b5fb60edf2f39432e6b65ff662")] + [InlineData('l', 32, "b29190b5fb60edf2f39432e6b65ff66216a9d1952bddf39a5ca98f5733f0716f")] + [InlineData('m', 16, "2be3c6b9a40e58d8498a4cba8492252b")] + [InlineData('m', 32, "2be3c6b9a40e58d8498a4cba8492252b41386129f3aeda88be7bb1f6f6d8a98c")] + [InlineData('n', 16, "b19698e3b6c338ee13082951975ca366")] + [InlineData('n', 32, "b19698e3b6c338ee13082951975ca366c01454b4447e4468664b68b88df81da9")] + [InlineData('o', 16, "fc45b64dee64820667da8ce089f1d670")] + [InlineData('o', 32, "fc45b64dee64820667da8ce089f1d6708059fe9b72145f0d974c00bca7c678ba")] + [InlineData('p', 16, "8de786bfe1d6dea5b32cba7febedd6ff")] + [InlineData('p', 32, "8de786bfe1d6dea5b32cba7febedd6ff144ab0e03fe85108c6270a719d572195")] + [InlineData('q', 16, "2d8e1bec7cd9bdaddff81fac8bf5773f")] + [InlineData('q', 32, "2d8e1bec7cd9bdaddff81fac8bf5773f7413082c1bb11d415b23bf376f872ba2")] + [InlineData('r', 16, "0c4e806212458a793a21390358704530")] + [InlineData('r', 32, "0c4e806212458a793a2139035870453078cba6a4cee11accd88e366db4b3662b")] + [InlineData('s', 16, "aaed5602244df2167017e5c0f2f682ec")] + [InlineData('s', 32, "aaed5602244df2167017e5c0f2f682ec5fa02fd58b7de9a7a264b6b6635b3d97")] + [InlineData('t', 16, "d72a9756dd8b448a638aa7758df2fc00")] + [InlineData('t', 32, "d72a9756dd8b448a638aa7758df2fc006eb3241e0924db117a584cb53b46aa9a")] + [InlineData('u', 16, "4d3948929081f779f08265b0abd3eea9")] + [InlineData('u', 32, "4d3948929081f779f08265b0abd3eea9ca8761783a7aa2532f6a724935de330d")] + [InlineData('v', 16, "6894f9ce4cf4da4028eb279cf53ca8af")] + [InlineData('v', 32, "6894f9ce4cf4da4028eb279cf53ca8afa78946cbfe6cfa1b3e5b672e107b20c9")] + [InlineData('w', 16, "83901a8d9dc152e79f2bfd4ec75790bd")] + [InlineData('w', 32, "83901a8d9dc152e79f2bfd4ec75790bd774546aa54c7590f82b6fea524ceb075")] + [InlineData('x', 16, "c851121abe8095973c9bdc1b446089f3")] + [InlineData('x', 32, "c851121abe8095973c9bdc1b446089f3249cf74e0b64660b61d73bcae0350f4d")] + [InlineData('y', 16, "0c0e7900a42d04a00afef323858bc461")] + [InlineData('y', 32, "0c0e7900a42d04a00afef323858bc461deb73fbf01343d3de7dee05f40f8057a")] + [InlineData('z', 16, "b9bb5914c3385c795584905092480f74")] + [InlineData('z', 32, "b9bb5914c3385c795584905092480f74cf633b662308cc1744c39136625b44c1")] + [InlineData('0', 16, "7e8b1406d903bc9137fb69e769742c8d")] + [InlineData('0', 32, "7e8b1406d903bc9137fb69e769742c8d3e36f1c4fed51a608809b08de9f3e4a0")] + [InlineData('1', 16, "2f169f9b4e6a1024752209cd5410ebb8")] + [InlineData('1', 32, "2f169f9b4e6a1024752209cd5410ebb84959eee0ac73c29a04c23bd524c12f81")] + [InlineData('2', 16, "a5a4f007abc4dfe1eb19f685efde94ca")] + [InlineData('2', 32, "a5a4f007abc4dfe1eb19f685efde94ca76f77dff7279de620dd52074b33fa1c6")] + [InlineData('3', 16, "08946cd494a2c00b0e9321af0c225309")] + [InlineData('3', 32, "08946cd494a2c00b0e9321af0c225309e9d1b9d14ce8eeb4ed5182031c3f29b0")] + [InlineData('4', 16, "1d8a904c4fff579bc28fd3a8065762b9")] + [InlineData('4', 32, "1d8a904c4fff579bc28fd3a8065762b958f81089579cf2177ae7489a90f7d396")] + [InlineData('5', 16, "172f84a65934fc29776758a22ad080b3")] + [InlineData('5', 32, "172f84a65934fc29776758a22ad080b341b497b1967d89a20dbd8420f4d4507b")] + [InlineData('6', 16, "cc2dc8d8adb6439605fa188ed5f0d8a4")] + [InlineData('6', 32, "cc2dc8d8adb6439605fa188ed5f0d8a43930b8e1eb8fc46e63dd9ab6a643910d")] + [InlineData('7', 16, "112a104bd5901f13abbfdcd11be28abf")] + [InlineData('7', 32, "112a104bd5901f13abbfdcd11be28abfeea892133b1861afe6cc4c999cc9c160")] + [InlineData('8', 16, "09dfb269bed6186424d76680f5b936b8")] + [InlineData('8', 32, "09dfb269bed6186424d76680f5b936b858b844472cbc5e1ea59d24282e8b3e31")] + [InlineData('9', 16, "0d869764040d76f626be277bc31072f1")] + [InlineData('9', 32, "0d869764040d76f626be277bc31072f1e85d9376223b23584817a2ba9834304f")] + public void Sha3Shake256ShouldProduceExpectedResult(char character, int length, string expected) + { + // Given + using HashAlgorithm algorithm = Sha3.CreateSha3Shake256(length); + + // When + Hash hash = Hash.Compute(algorithm, [character]); + string actual = hash.ToString(); + + // Then + Assert.Equal(expected, actual); + } +} diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs deleted file mode 100644 index 2755a50..0000000 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Constants.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct DigitalSignature -{ - /// - /// Gets an empty digital signature value. - /// - public static DigitalSignature Empty => Create(EmptyArray()); -} diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs deleted file mode 100644 index c7710f8..0000000 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Create.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct DigitalSignature -{ - /// - /// Creates a instance from the specified digitally signed data. - /// - /// The digitally signed data. - /// Returns a instance from the specified digitally signed data. - public static DigitalSignature Create(byte[] value) - { - return new DigitalSignature(value); - } - - /// - /// Creates a from the specified value. - /// - /// The Base-16 from which to construct a signature value. - /// Returns an from the specified Base-16 value. - public static DigitalSignature Create(Base16 value) - { - byte[] bytes = value.ToByteArray(); - return Create(bytes); - } - - /// - /// Creates a from the specified value. - /// - /// The Base-32 from which to construct a signature value. - /// Returns an from the specified Base-32 value. - public static DigitalSignature Create(Base32 value) - { - byte[] bytes = value.ToByteArray(); - return Create(bytes); - } - - /// - /// Creates a from the specified value. - /// - /// The Base-58 from which to construct a signature value. - /// Returns an from the specified Base-58 value. - public static DigitalSignature Create(Base58 value) - { - byte[] bytes = value.ToByteArray(); - return Create(bytes); - } - - /// - /// Creates a from the specified value. - /// - /// The Base-64 from which to construct a signature value. - /// Returns an from the specified Base-64 value. - public static DigitalSignature Create(Base64 value) - { - byte[] bytes = value.ToByteArray(); - return Create(bytes); - } -} diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs index 63e5058..6d6eed8 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,60 +12,59 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Linq; using OnixLabs.Core.Linq; namespace OnixLabs.Security.Cryptography; -public readonly partial struct DigitalSignature : IEquatable +public readonly partial struct DigitalSignature { /// - /// Checks for equality between this instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . public bool Equals(DigitalSignature other) { - return other.Value.SequenceEqual(Value); + return value.SequenceEqual(other.value); } /// - /// Checks for equality between this instance and another object. + /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return obj is DigitalSignature other && Equals(other); } /// - /// Serves as a hash code function for this instance. + /// Serves as a hash code function for the current instance. /// - /// A hash code for this instance. + /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(Value.GetContentHashCode()); + return value.GetContentHashCode(); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(DigitalSignature left, DigitalSignature right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(DigitalSignature left, DigitalSignature right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs index db89849..73e4f4f 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.To.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.To.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,63 +14,26 @@ using System; using OnixLabs.Core; -using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; public readonly partial struct DigitalSignature { /// - /// Returns a byte array containing the underlying signed data. + /// Gets the underlying representation of the current instance. /// - /// A byte array containing the underlying signed data. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { - return Value.Copy(); + return value.Copy(); } /// - /// Returns a value that represents the underlying signature data. + /// Returns a that represents the current object. /// - /// Returns a value that represents the underlying signature data. - public Base16 ToBase16() - { - return Base16.Create(Value); - } - - /// - /// Returns a value that represents the underlying signature data. - /// - /// Returns a value that represents the underlying signature data. - public Base32 ToBase32() - { - return Base32.Create(Value); - } - - /// - /// Returns a value that represents the underlying signature data. - /// - /// Returns a value that represents the underlying signature data. - public Base58 ToBase58() - { - return Base58.Create(Value); - } - - /// - /// Returns a value that represents the underlying signature data. - /// - /// Returns a value that represents the underlying signature data. - public Base64 ToBase64() - { - return Base64.Create(Value); - } - - /// - /// Returns a that represents the current object. - /// - /// A that represents the current object. + /// Returns a that represents the current object. public override string ToString() { - return Convert.ToHexString(Value).ToLower(); + return Convert.ToHexString(value).ToLower(); } } diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs b/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs deleted file mode 100644 index 11aff44..0000000 --- a/OnixLabs.Security.Cryptography/DigitalSignature.Validation.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Security.Cryptography; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct DigitalSignature -{ - /// - /// Determines whether this is valid, given the specified unsigned data and public key. - /// - /// The unsigned data to validate. - /// The public key to validate. - /// Returns if this is valid; otherwise, . - public bool IsDataValid(byte[] unsignedData, PublicKey key) - { - return key.IsDataValid(this, unsignedData); - } - - /// - /// Determines whether this is valid, given the specified unsigned hash and public key. - /// - /// The unsigned data to validate. - /// The public key to validate. - /// Returns if this is valid; otherwise, . - public bool IsHashValid(byte[] unsignedHash, PublicKey key) - { - return key.IsHashValid(this, unsignedHash); - } - - /// - /// Determines whether this is valid, given the specified unsigned hash and public key. - /// - /// The unsigned data to validate. - /// The public key to validate. - /// Returns if this is valid; otherwise, . - public bool IsHashValid(Hash unsignedHash, PublicKey key) - { - byte[] unsignedHashBytes = unsignedHash.ToByteArray(); - return IsHashValid(unsignedHashBytes, key); - } - - /// - /// Verifies this . - /// - /// The unsigned data to verify. - /// The public key to verify. - /// If this was not signed by the specified key. - public void VerifyData(byte[] unsignedData, PublicKey key) - { - if (!IsDataValid(unsignedData, key)) - { - throw new CryptographicException("The specified digital signature was not signed with this key."); - } - } - - /// - /// Verifies this . - /// - /// The unsigned hash to verify. - /// The public key to verify. - /// If this was not signed by the specified key. - public void VerifyHash(byte[] unsignedHash, PublicKey key) - { - if (!IsHashValid(unsignedHash, key)) - { - throw new CryptographicException("The specified digital signature was not signed with this key."); - } - } - - /// - /// Verifies this . - /// - /// The unsigned hash to verify. - /// The public key to verify. - /// If this was not signed by the specified key. - public void VerifyHash(Hash unsignedHash, PublicKey key) - { - byte[] unsignedHashBytes = unsignedHash.ToByteArray(); - VerifyHash(unsignedHashBytes, key); - } -} diff --git a/OnixLabs.Security.Cryptography/DigitalSignature.cs b/OnixLabs.Security.Cryptography/DigitalSignature.cs index d44a6b7..43d8b4b 100644 --- a/OnixLabs.Security.Cryptography/DigitalSignature.cs +++ b/OnixLabs.Security.Cryptography/DigitalSignature.cs @@ -1,37 +1,26 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core; +using System; namespace OnixLabs.Security.Cryptography; /// -/// Represents a digital signature. +/// Represents a cryptographic digital signature. /// -public readonly partial struct DigitalSignature +/// The underlying value of the cryptographic digital signature. +public readonly partial struct DigitalSignature(ReadOnlySpan value) : ICryptoPrimitive { - /// - /// Initializes a new instance of the struct. - /// - /// The digitally signed data. - private DigitalSignature(byte[] value) - { - Value = value.Copy(); - } - - /// - /// Gets the underlying digitally signed data. - /// - private byte[] Value { get; } + private readonly byte[] value = value.ToArray(); } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs index 931b937..532c2fc 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Create.cs @@ -1,80 +1,55 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core; -using OnixLabs.Core.Text; +using System.Security.Cryptography; namespace OnixLabs.Security.Cryptography; public sealed partial class EcdsaPrivateKey { /// - /// Creates an from the specified key data and hash algorithm type. + /// Creates a new ECDSA cryptographic private key. /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey Create(byte[] key, HashAlgorithmType type) + /// Returns a new instance. + public static EcdsaPrivateKey Create() { - return new EcdsaPrivateKey(key.Copy(), type); + using ECDsa key = ECDsa.Create(); + byte[] keyData = key.ExportECPrivateKey(); + return new EcdsaPrivateKey(keyData); } /// - /// Creates an from the specified value. + /// Creates a new ECDSA cryptographic private key. /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey Create(Base16 key, HashAlgorithmType type) + /// The elliptic curve from which to create a new ECDSA cryptographic private key. + /// Returns a new instance. + public static EcdsaPrivateKey Create(ECCurve curve) { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type); + using ECDsa key = ECDsa.Create(curve); + byte[] keyData = key.ExportECPrivateKey(); + return new EcdsaPrivateKey(keyData); } /// - /// Creates an from the specified value. + /// Creates a new ECDSA cryptographic private key. /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey Create(Base32 key, HashAlgorithmType type) + /// The elliptic curve parameters from which to create a new ECDSA cryptographic private key. + /// Returns a new instance. + public static EcdsaPrivateKey Create(ECParameters parameters) { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey Create(Base58 key, HashAlgorithmType type) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPrivateKey Create(Base64 key, HashAlgorithmType type) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type); + using ECDsa key = ECDsa.Create(parameters); + byte[] keyData = key.ExportECPrivateKey(); + return new EcdsaPrivateKey(keyData); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs index 53f8083..42a4ce4 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Export.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,26 +20,24 @@ namespace OnixLabs.Security.Cryptography; public sealed partial class EcdsaPrivateKey { /// - /// Exports the key in PKCS #8 format. + /// Exports the ECDSA cryptographic private key data in PKCS #8 format. /// - /// Returns the key in PKCS #8 format. - public override byte[] ExportPkcs8Key() + /// Returns a new instance containing the ECDSA cryptographic private key data in PKCS #8 format. + public override byte[] ExportPkcs8PrivateKey() { - using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); - return privateKey.ExportPkcs8PrivateKey(); + using ECDsa key = ImportKeyData(); + return key.ExportPkcs8PrivateKey(); } /// - /// Exports the key in encrypted PKCS #8 format. + /// Exports the ECDSA cryptographic private key data in encrypted PKCS #8 format. /// /// The password to use for encryption. /// The parameters required for password based encryption. - /// Returns the key in encrypted PKCS #8 format. - public override byte[] ExportPkcs8Key(ReadOnlySpan password, PbeParameters parameters) + /// Returns a new instance containing the ECDSA cryptographic private key data in PKCS #8 format. + public override byte[] ExportPkcs8PrivateKey(ReadOnlySpan password, PbeParameters parameters) { - using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); - return privateKey.ExportEncryptedPkcs8PrivateKey(password, parameters); + using ECDsa key = ImportKeyData(); + return key.ExportEncryptedPkcs8PrivateKey(password, parameters); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs index 6a4c06e..63f7102 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Get.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,14 +19,13 @@ namespace OnixLabs.Security.Cryptography; public sealed partial class EcdsaPrivateKey { /// - /// Gets the public key component from this private key. + /// Gets the ECDSA cryptographic public key component from the current ECDSA cryptographic private key. /// - /// Returns the public key component from this private key. - public override PublicKey GetPublicKey() + /// Returns a new instance containing the ECDSA cryptographic public key component from the current ECDSA cryptographic private key. + public override EcdsaPublicKey GetPublicKey() { - using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); - byte[] publicKey = privateKey.ExportSubjectPublicKeyInfo(); - return new EcdsaPublicKey(publicKey, AlgorithmType); + using ECDsa key = ImportKeyData(); + byte[] keyData = key.ExportSubjectPublicKeyInfo(); + return new EcdsaPublicKey(keyData); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs index 6ffa465..6650422 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Import.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,108 +20,63 @@ namespace OnixLabs.Security.Cryptography; public sealed partial class EcdsaPrivateKey { /// - /// Imports a PKCS #8 formatted key. + /// Imports the ECDSA cryptographic private key data in PKCS #8 format. /// - /// The key data to import. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static EcdsaPrivateKey ImportPkcs8Key(ReadOnlySpan data, HashAlgorithmType type) + /// The cryptographic private key data to import. + /// Returns a new instance from the imported cryptographic private key data. + public static EcdsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data) { - ECDsa privateKey = ECDsa.Create(); - privateKey.ImportPkcs8PrivateKey(data, out int _); - byte[] bytes = privateKey.ExportECPrivateKey(); - return Create(bytes, type); + return ImportPkcs8PrivateKey(data, out int _); } /// - /// Imports a PKCS #8 formatted key. + /// Imports the ECDSA cryptographic private key data in PKCS #8 format. /// - /// The key data to import. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static EcdsaPrivateKey ImportPkcs8Key(byte[] data, HashAlgorithmType type) + /// The cryptographic private key data to import. + /// The number of bytes read from the input data. + /// Returns a new instance from the imported cryptographic private key data. + public static EcdsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, out int bytesRead) { - ReadOnlySpan bytes = data.AsSpan(); - return ImportPkcs8Key(bytes, type); + using ECDsa key = ECDsa.Create(); + key.ImportPkcs8PrivateKey(data, out bytesRead); + byte[] keyData = key.ExportECPrivateKey(); + return new EcdsaPrivateKey(keyData); } /// - /// Imports an encrypted PKCS #8 formatted key. + /// Imports the ECDSA cryptographic private key data in encrypted PKCS #8 format. /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static EcdsaPrivateKey ImportPkcs8Key(ReadOnlySpan data, ReadOnlySpan password, HashAlgorithmType type) + /// The cryptographic private key data to import. + /// The password required for password based decryption. + /// Returns a new instance from the imported cryptographic private key data. + public static EcdsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, ReadOnlySpan password) { - ECDsa privateKey = ECDsa.Create(); - privateKey.ImportEncryptedPkcs8PrivateKey(password, data, out int _); - byte[] bytes = privateKey.ExportECPrivateKey(); - return Create(bytes, type); + return ImportPkcs8PrivateKey(data, password, out int _); } /// - /// Imports an encrypted PKCS #8 formatted key. + /// Imports the ECDSA cryptographic private key data in encrypted PKCS #8 format. /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static EcdsaPrivateKey ImportPkcs8Key(ReadOnlySpan data, char[] password, HashAlgorithmType type) + /// The cryptographic private key data to import. + /// The password required for password based decryption. + /// The number of bytes read from the input data. + /// Returns a new instance from the imported cryptographic private key data. + public static EcdsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, ReadOnlySpan password, out int bytesRead) { - ReadOnlySpan characters = password.AsSpan(); - return ImportPkcs8Key(data, characters, type); + using ECDsa key = ECDsa.Create(); + key.ImportEncryptedPkcs8PrivateKey(password, data, out bytesRead); + byte[] keyData = key.ExportECPrivateKey(); + return new EcdsaPrivateKey(keyData); } /// - /// Imports an encrypted PKCS #8 formatted key. + /// Imports the key data into a new instance. /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static EcdsaPrivateKey ImportPkcs8Key(ReadOnlySpan data, string password, HashAlgorithmType type) + /// Returns a new instance containing the imported key data. + private ECDsa ImportKeyData() { - ReadOnlySpan characters = password.AsSpan(); - return ImportPkcs8Key(data, characters, type); - } - - /// - /// Imports an encrypted PKCS #8 formatted key. - /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static EcdsaPrivateKey ImportPkcs8Key(byte[] data, ReadOnlySpan password, HashAlgorithmType type) - { - ReadOnlySpan bytes = data.AsSpan(); - return ImportPkcs8Key(bytes, password, type); - } - - /// - /// Imports an encrypted PKCS #8 formatted key. - /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static EcdsaPrivateKey ImportPkcs8Key(byte[] data, char[] password, HashAlgorithmType type) - { - ReadOnlySpan bytes = data.AsSpan(); - return ImportPkcs8Key(bytes, password, type); - } - - /// - /// Imports an encrypted PKCS #8 formatted key. - /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static EcdsaPrivateKey ImportPkcs8Key(byte[] data, string password, HashAlgorithmType type) - { - ReadOnlySpan bytes = data.AsSpan(); - return ImportPkcs8Key(bytes, password, type); + ECDsa algorithm = ECDsa.Create(); + algorithm.ImportECPrivateKey(KeyData, out int _); + return algorithm; } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs index 3562fac..652c2d7 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.Sign.cs @@ -1,47 +1,155 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.IO; using System.Security.Cryptography; +using OnixLabs.Core; namespace OnixLabs.Security.Cryptography; public sealed partial class EcdsaPrivateKey { /// - /// Computes a from the specified unsigned data. + /// Hashes the specified data and signs the resulting hash. /// - /// The unsigned data from which to compute a . - /// Returns a from the specified unsigned data. - public override DigitalSignature SignData(byte[] unsignedData) + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default) { - using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); - HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - byte[] signedData = privateKey.SignData(unsignedData, name); - return DigitalSignature.Create(signedData); + byte[] hash = algorithm.ComputeHash(data.ToArray()); + return SignHash(hash, format); } /// - /// Computes a from the specified unsigned hash. + /// Hashes the specified data and signs the resulting hash. /// - /// The unsigned hash from which to compute a . - /// Returns a from the specified unsigned hash. - public override DigitalSignature SignHash(byte[] unsignedHash) + /// The input data to hash and sign. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default) { - using ECDsa privateKey = ECDsa.Create(); - privateKey.ImportECPrivateKey(KeyData, out int _); - byte[] signedData = privateKey.SignHash(unsignedHash); - return DigitalSignature.Create(signedData); + byte[] hash = algorithm.ComputeHash(data.ToArray(), offset, count); + return SignHash(hash, format); + } + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + byte[] hash = algorithm.ComputeHash(data); + return SignHash(hash, format); + } + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + byte[] hash = algorithm.ComputeHash(data.ToByteArray()); + return SignHash(hash, format); + } + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.SignData(data, algorithm, format); + } + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.SignData(data.ToArray(), offset, count, algorithm, format); + } + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.SignData(data, algorithm, format); + } + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.SignData(data.ToByteArray(), algorithm, format); + } + + /// + /// Signs the specified . + /// + /// The hash to sign. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignHash(Hash hash, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.SignHash(hash.ToByteArray(), format); + } + + /// + /// Signs the specified . + /// + /// The hash to sign. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignHash(ReadOnlySpan hash, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.SignHash(hash, format); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs index 2a9d4e3..2f1f65c 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPrivateKey.cs @@ -1,30 +1,23 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; + namespace OnixLabs.Security.Cryptography; /// -/// Represents an ECDSA private key. +/// Represents an ECDSA cryptographic private key. /// -public sealed partial class EcdsaPrivateKey : PrivateKey -{ - /// - /// Creates a new instance of the class. - /// - /// The private key data. - /// The hash algorithm type for computing signature data. - internal EcdsaPrivateKey(byte[] data, HashAlgorithmType type) : base(data, type) - { - } -} +/// The underlying key data of the ECDSA cryptographic private key. +public sealed partial class EcdsaPrivateKey(ReadOnlySpan keyData) : PrivateKey(keyData), IEcdsaPrivateKey; diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs deleted file mode 100644 index 8aeee19..0000000 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Create.cs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core; -using OnixLabs.Core.Text; - -namespace OnixLabs.Security.Cryptography; - -public sealed partial class EcdsaPublicKey -{ - /// - /// Creates an from the specified key data and hash algorithm type. - /// - /// The key data from which to construct a public key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey Create(byte[] key, HashAlgorithmType type) - { - return new EcdsaPublicKey(key.Copy(), type); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey Create(Base16 key, HashAlgorithmType type) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey Create(Base32 key, HashAlgorithmType type) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey Create(Base58 key, HashAlgorithmType type) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static EcdsaPublicKey Create(Base64 key, HashAlgorithmType type) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type); - } -} diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Import.cs similarity index 58% rename from OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs rename to OnixLabs.Security.Cryptography/EcdsaPublicKey.Import.cs index 29af453..a642f50 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Import.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,17 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.Security.Cryptography; + namespace OnixLabs.Security.Cryptography; -public sealed partial class RsaPrivateKey +public sealed partial class EcdsaPublicKey { /// - /// Checks for equality between this instance and another object. + /// Imports the key data into a new instance. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public override bool Equals(PrivateKey? other) + /// Returns a new instance containing the imported key data. + private ECDsa ImportKeyData() { - return base.Equals(other) && other is RsaPrivateKey rsaOther && rsaOther.Padding == Padding; + ECDsa algorithm = ECDsa.Create(); + algorithm.ImportSubjectPublicKeyInfo(KeyData, out int _); + return algorithm; } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs index ac2b6ff..1191106 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.Verify.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,38 +12,655 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.IO; using System.Security.Cryptography; +using OnixLabs.Core; namespace OnixLabs.Security.Cryptography; public sealed partial class EcdsaPublicKey { /// - /// Determines whether the specified was signed by the private component of this public key. + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. /// - /// The to validate. - /// The unsigned data to validate. - /// Returns if the specified was signed by the private component of this public key; otherwise, . - public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData) + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default) { - using ECDsa publicKey = ECDsa.Create(); - publicKey.ImportSubjectPublicKeyInfo(KeyData, out int _); - byte[] signatureData = signature.ToByteArray(); - HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - return publicKey.VerifyData(unsignedData, signatureData, name); + byte[] hash = algorithm.ComputeHash(data.ToArray()); + return IsHashValid(signature, hash, format); } /// - /// Determines whether the specified was signed by the private component of this public key. + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. /// - /// The to validate. - /// The unsigned hash to validate. - /// Returns if the specified was signed by the private component of this public key; otherwise, . - public override bool IsHashValid(DigitalSignature signature, byte[] unsignedHash) + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default) { - using ECDsa publicKey = ECDsa.Create(); - publicKey.ImportSubjectPublicKeyInfo(KeyData, out int _); - byte[] signatureData = signature.ToByteArray(); - return publicKey.VerifyHash(unsignedHash, signatureData); + byte[] hash = algorithm.ComputeHash(data.ToArray(), offset, count); + return IsHashValid(signature, hash, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + byte[] hash = algorithm.ComputeHash(data); + return IsHashValid(signature, hash, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + byte[] hash = algorithm.ComputeHash(data.ToByteArray()); + return IsHashValid(signature, hash, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyData(data, signature, algorithm, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyData(data.ToArray(), offset, count, signature.ToArray(), algorithm, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyData(data, signature.ToArray(), algorithm, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyData(data.ToByteArray(), signature, algorithm, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + byte[] hash = algorithm.ComputeHash(data.ToArray()); + return IsHashValid(signature, hash, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + byte[] hash = algorithm.ComputeHash(data.ToArray(), offset, count); + return IsHashValid(signature, hash, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + byte[] hash = algorithm.ComputeHash(data); + return IsHashValid(signature, hash, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + byte[] hash = algorithm.ComputeHash(data.ToByteArray()); + return IsHashValid(signature, hash, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyData(data, signature.ToByteArray(), algorithm, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyData(data.ToArray(), offset, count, signature.ToByteArray(), algorithm, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyData(data, signature.ToByteArray(), algorithm, format); + } + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyData(data.ToByteArray(), signature.ToByteArray(), algorithm, format); + } + + /// + /// Determines whether the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsHashValid(ReadOnlySpan signature, Hash hash, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyHash(hash.ToByteArray(), signature, format); + } + + /// + /// Determines whether the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsHashValid(ReadOnlySpan signature, ReadOnlySpan hash, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyHash(hash, signature, format); + } + + /// + /// Determines whether the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsHashValid(DigitalSignature signature, Hash hash, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyHash(hash.ToByteArray(), signature.ToByteArray(), format); + } + + /// + /// Determines whether the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsHashValid(DigitalSignature signature, ReadOnlySpan hash, DSASignatureFormat format = default) + { + using ECDsa key = ImportKeyData(); + return key.VerifyHash(hash, signature.ToByteArray(), format); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, offset, count, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(ReadOnlySpan signature, Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, offset, count, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(ReadOnlySpan signature, Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(DigitalSignature signature, ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, offset, count, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(DigitalSignature signature, Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(DigitalSignature signature, IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(DigitalSignature signature, ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, offset, count, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(DigitalSignature signature, Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyData(DigitalSignature signature, IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default) + { + CheckSignature(IsDataValid(signature, data, algorithm, format)); + } + + /// + /// Verifies that the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyHash(ReadOnlySpan signature, Hash hash, DSASignatureFormat format = default) + { + CheckSignature(IsHashValid(signature, hash, format)); + } + + /// + /// Verifies that the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyHash(ReadOnlySpan signature, ReadOnlySpan hash, DSASignatureFormat format = default) + { + CheckSignature(IsHashValid(signature, hash, format)); + } + + /// + /// Verifies that the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyHash(DigitalSignature signature, Hash hash, DSASignatureFormat format = default) + { + CheckSignature(IsHashValid(signature, hash, format)); + } + + /// + /// Verifies that the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + public void VerifyHash(DigitalSignature signature, ReadOnlySpan hash, DSASignatureFormat format = default) + { + CheckSignature(IsHashValid(signature, hash, format)); + } + + /// + /// Performs a signature check pre-condition that throws a in the event that the specified condition is . + /// + /// The signature condition to check. + /// If the specified condition is . + private static void CheckSignature(bool condition) + { + if (condition) return; + + const string message = "The specified digital signature could not be verified. Either the specified data is incorrect, " + + "or the data was not signed with a private key corresponding to the current public key."; + + throw new CryptographicException(message); } } diff --git a/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs b/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs index d372145..97f92c3 100644 --- a/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs +++ b/OnixLabs.Security.Cryptography/EcdsaPublicKey.cs @@ -1,30 +1,23 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; + namespace OnixLabs.Security.Cryptography; /// -/// Represents an ECDSA public key. +/// Represents an ECDSA cryptographic public key. /// -public sealed partial class EcdsaPublicKey : PublicKey -{ - /// - /// Creates a new instance of the class. - /// - /// The public key data. - /// The hash algorithm type for computing signature data. - internal EcdsaPublicKey(byte[] data, HashAlgorithmType type) : base(data, type) - { - } -} +/// The underlying key data of the ECDSA cryptographic public key. +public sealed partial class EcdsaPublicKey(ReadOnlySpan keyData) : PublicKey(keyData), IEcdsaPublicKey; diff --git a/OnixLabs.Security.Cryptography/Extensions.HashAlgorithm.cs b/OnixLabs.Security.Cryptography/Extensions.HashAlgorithm.cs new file mode 100644 index 0000000..97f9678 --- /dev/null +++ b/OnixLabs.Security.Cryptography/Extensions.HashAlgorithm.cs @@ -0,0 +1,103 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.ComponentModel; +using System.IO; +using System.Security.Cryptography; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography; + +/// +/// Provides extension methods for hash algorithms. +/// +[EditorBrowsable(EditorBrowsableState.Never)] +public static class HashAlgorithmExtensions +{ + /// + /// Computes the hash value for the specified byte array. + /// + /// The which will be used to compute a hash value. + /// The input data to compute the hash for. + /// The number of rounds that the input data should be hashed. + /// Returns the computed hash value. + public static byte[] ComputeHash(this HashAlgorithm algorithm, byte[] data, int rounds) + { + return algorithm.ComputeHash(new MemoryStream(data), rounds); + } + + /// + /// Computes the hash value for the specified byte array. + /// + /// The which will be used to compute a hash value. + /// The input data to compute the hash for. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The number of rounds that the input data should be hashed. + /// Returns the computed hash value. + public static byte[] ComputeHash(this HashAlgorithm algorithm, byte[] data, int offset, int count, int rounds) + { + return algorithm.ComputeHash(data.Copy(offset, count), rounds); + } + + /// + /// Computes the hash value for the specified . + /// + /// The which will be used to compute a hash value. + /// The input data to compute the hash for. + /// The which will be used to convert the specified . + /// The number of rounds that the input data should be hashed. + /// Returns the computed hash value. + public static byte[] ComputeHash(this HashAlgorithm algorithm, ReadOnlySpan data, Encoding? encoding = null, int rounds = 1) + { + return algorithm.ComputeHash((encoding ?? Encoding.Default).GetBytes(data.ToArray()), rounds); + } + + /// + /// Computes the hash value for the specified object. + /// + /// The which will be used to compute a hash value. + /// The input data to compute the hash for. + /// The number of rounds that the input data should be hashed. + /// Returns the computed hash value. + public static byte[] ComputeHash(this HashAlgorithm algorithm, Stream stream, int rounds) + { + Require(rounds > 0, "Rounds must be greater than zero", nameof(rounds)); + + byte[] data = algorithm.ComputeHash(stream); + while (--rounds > 0) data = algorithm.ComputeHash(data); + return data; + } + + /// + /// Asynchronously computes the hash value for the specified object. + /// + /// The which will be used to compute a hash value. + /// The input data to compute the hash for. + /// The number of rounds that the input data should be hashed. + /// The token to monitor for cancellation requests. + /// Returns a task that represents the asynchronous compute hash operation and wraps the computed hash value. + public static async Task ComputeHashAsync(this HashAlgorithm algorithm, Stream stream, int rounds, CancellationToken token = default) + { + Require(rounds > 0, "Rounds must be greater than zero", nameof(rounds)); + + MemoryStream memoryStream = new(await algorithm.ComputeHashAsync(stream, token)); + while (--rounds > 0) memoryStream = new MemoryStream(await algorithm.ComputeHashAsync(memoryStream, token)); + return memoryStream.ToArray(); + } +} diff --git a/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs b/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs deleted file mode 100644 index ab198ee..0000000 --- a/OnixLabs.Security.Cryptography/Hash.AllOneHash.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Creates an all-one hash of the specified length. This will create a hash of an unknown type. - /// - /// The length of the hash in bytes. - /// Returns an all-one of the specified length. - public static Hash CreateAllOneHash(int length) - { - return CreateAllOneHash(HashAlgorithmType.Unknown, length); - } - - /// - /// Creates an all-one hash of the specified hash algorithm type. - /// - /// The type of hash to create. - /// Returns an all-one of the specified hash algorithm type. - public static Hash CreateAllOneHash(HashAlgorithmType type) - { - return CreateAllOneHash(type, type.Length); - } - - /// - /// Creates an all-one hash of the specified hash algorithm type and length. - /// - /// The type of hash to create. - /// The length of the hash in bytes. - /// Returns an all-one of the specified hash algorithm type and length. - /// If the length of the hash is unexpected. - public static Hash CreateAllOneHash(HashAlgorithmType type, int length) - { - Require(type.IsUnknown || type.Length == length, "Unexpected hash algorithm output length.", nameof(length)); - byte[] bytes = Enumerable.Repeat(byte.MaxValue, length).ToArray(); - return Create(bytes, type); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs b/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs deleted file mode 100644 index 6063f12..0000000 --- a/OnixLabs.Security.Cryptography/Hash.AllZeroHash.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Creates an all-zero hash of the specified length. This will create a hash of an unknown type. - /// - /// The length of the hash in bytes. - /// Returns an all-zero of the specified length. - public static Hash CreateAllZeroHash(int length) - { - return CreateAllZeroHash(HashAlgorithmType.Unknown, length); - } - - /// - /// Creates an all-zero hash of the specified hash algorithm type. - /// - /// The type of hash to create. - /// Returns an all-zero of the specified hash algorithm type. - public static Hash CreateAllZeroHash(HashAlgorithmType type) - { - return CreateAllZeroHash(type, type.Length); - } - - /// - /// Creates an all-zero hash of the specified hash algorithm type and length. - /// - /// The type of hash to create. - /// The length of the hash in bytes. - /// Returns an all-zero of the specified hash algorithm type and length. - /// If the length of the hash is unexpected. - public static Hash CreateAllZeroHash(HashAlgorithmType type, int length) - { - Require(type.IsUnknown || type.Length == length, "Unexpected hash algorithm output length.", nameof(length)); - byte[] bytes = Enumerable.Repeat(byte.MinValue, length).ToArray(); - return Create(bytes, type); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Comparable.cs b/OnixLabs.Security.Cryptography/Hash.Comparable.cs index 932689b..15418f8 100644 --- a/OnixLabs.Security.Cryptography/Hash.Comparable.cs +++ b/OnixLabs.Security.Cryptography/Hash.Comparable.cs @@ -1,21 +1,37 @@ -using System; +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + using System.Numerics; using OnixLabs.Core; namespace OnixLabs.Security.Cryptography; -public readonly partial struct Hash : IComparable, IComparable +public readonly partial struct Hash { /// /// Compares the current instance with another object of the same type and returns an integer that indicates /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the /// other object. /// - /// An object to compare with this instance. + /// An object to compare with this instance. /// Returns a value that indicates the relative order of the objects being compared. - public int CompareTo(object? obj) + public int CompareTo(Hash other) { - return this.CompareObject(obj); + BigInteger left = new(value); + BigInteger right = new(other.value); + + return left.CompareTo(right); } /// @@ -23,13 +39,54 @@ public int CompareTo(object? obj) /// whether the current instance precedes, follows, or occurs in the same position in the sort order as the /// other object. /// - /// An object to compare with this instance. + /// An object to compare with this instance. /// Returns a value that indicates the relative order of the objects being compared. - public int CompareTo(Hash other) + public int CompareTo(object? obj) { - BigInteger left = new(ToByteArray()); - BigInteger right = new(other.ToByteArray()); + return this.CompareToObject(obj); + } - return left.CompareTo(right); + /// + /// Performs a greater than comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is greater than the right-hand instance; otherwise, . + public static bool operator >(Hash left, Hash right) + { + return left.CompareTo(right) is 1; + } + + /// + /// Performs a greater than or equal comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is greater than or equal to the right-hand instance; otherwise, . + public static bool operator >=(Hash left, Hash right) + { + return left.CompareTo(right) is 0 or 1; + } + + /// + /// Performs a less than comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is less than the right-hand instance; otherwise, . + public static bool operator <(Hash left, Hash right) + { + return left.CompareTo(right) is -1; + } + + /// + /// Performs a less than or equal comparison between two object instances. + /// + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is less than or equal to the right-hand instance; otherwise, . + public static bool operator <=(Hash left, Hash right) + { + return left.CompareTo(right) is 0 or -1; } } diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs deleted file mode 100644 index 4124d5a..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Md5Hash.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes an MD5 hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeMd5Hash(string value) - { - return ComputeMd5Hash(value, Encoding.Default); - } - - /// - /// Computes an MD5 hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeMd5Hash(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Md5Hash, encoding); - } - - /// - /// Computes an MD5 hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeMd5Hash(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Md5Hash); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs deleted file mode 100644 index 75afcec..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha1Hash.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-1 hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha1Hash(string value) - { - return ComputeSha1Hash(value, Encoding.Default); - } - - /// - /// Computes a SHA-1 hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeSha1Hash(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Sha1Hash, encoding); - } - - /// - /// Computes a SHA-1 hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha1Hash(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Sha1Hash); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs deleted file mode 100644 index ec0372e..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash256.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-2 256-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha2Hash256(string value) - { - return ComputeSha2Hash256(value, Encoding.Default); - } - - /// - /// Computes a SHA-2 256-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeSha2Hash256(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Sha2Hash256, encoding); - } - - /// - /// Computes a SHA-2 256-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha2Hash256(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Sha2Hash256); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs deleted file mode 100644 index 3e9660f..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash384.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-2 384-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha2Hash384(string value) - { - return ComputeSha2Hash384(value, Encoding.Default); - } - - /// - /// Computes a SHA-2 384-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeSha2Hash384(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Sha2Hash384, encoding); - } - - /// - /// Computes a SHA-2 384-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha2Hash384(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Sha2Hash384); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs deleted file mode 100644 index c50f5b1..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha2Hash512.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-2 512-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha2Hash512(string value) - { - return ComputeSha2Hash512(value, Encoding.Default); - } - - /// - /// Computes a SHA-2 512-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeSha2Hash512(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Sha2Hash512, encoding); - } - - /// - /// Computes a SHA-2 512-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha2Hash512(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Sha2Hash512); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs deleted file mode 100644 index 5cb6b18..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash224.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 224-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha3Hash224(string value) - { - return ComputeSha3Hash224(value, Encoding.Default); - } - - /// - /// Computes a SHA-3 224-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeSha3Hash224(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Sha3Hash224, encoding); - } - - /// - /// Computes a SHA-3 224-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha3Hash224(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Sha3Hash224); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs deleted file mode 100644 index 691c709..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash256.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 256-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha3Hash256(string value) - { - return ComputeSha3Hash256(value, Encoding.Default); - } - - /// - /// Computes a SHA-3 256-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeSha3Hash256(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Sha3Hash256, encoding); - } - - /// - /// Computes a SHA-3 256-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha3Hash256(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Sha3Hash256); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs deleted file mode 100644 index 72f1170..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash384.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 384-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha3Hash384(string value) - { - return ComputeSha3Hash384(value, Encoding.Default); - } - - /// - /// Computes a SHA-3 384-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeSha3Hash384(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Sha3Hash384, encoding); - } - - /// - /// Computes a SHA-3 384-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha3Hash384(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Sha3Hash384); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs deleted file mode 100644 index ed9b710..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Hash512.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 512-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha3Hash512(string value) - { - return ComputeSha3Hash512(value, Encoding.Default); - } - - /// - /// Computes a SHA-3 512-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static Hash ComputeSha3Hash512(string value, Encoding encoding) - { - return ComputeHash(value, HashAlgorithmType.Sha3Hash512, encoding); - } - - /// - /// Computes a SHA-3 512-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static Hash ComputeSha3Hash512(byte[] value) - { - return ComputeHash(value, HashAlgorithmType.Sha3Hash512); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs deleted file mode 100644 index 32d9895..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake128.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 Shake 128-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static Hash ComputeSha3Shake128(string value, int length) - { - return ComputeSha3Shake128(value, Encoding.Default, length); - } - - /// - /// Computes a SHA-3 Shake 128-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static Hash ComputeSha3Shake128(string value, Encoding encoding, int length) - { - return ComputeHash(value, HashAlgorithmType.Sha3Shake128, encoding, length); - } - - /// - /// Computes a SHA-3 Shake 128-bit hash from the specified value. - /// - /// The input value to hash. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static Hash ComputeSha3Shake128(byte[] value, int length) - { - return ComputeHash(value, HashAlgorithmType.Sha3Shake128, length); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs deleted file mode 100644 index 60e8561..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Compute.Sha3Shake256.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 Shake 256-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static Hash ComputeSha3Shake256(string value, int length) - { - return ComputeSha3Shake256(value, Encoding.Default, length); - } - - /// - /// Computes a SHA-3 Shake 256-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static Hash ComputeSha3Shake256(string value, Encoding encoding, int length) - { - return ComputeHash(value, HashAlgorithmType.Sha3Shake256, encoding, length); - } - - /// - /// Computes a SHA-3 Shake 256-bit hash from the specified value. - /// - /// The input value to hash. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static Hash ComputeSha3Shake256(byte[] value, int length) - { - return ComputeHash(value, HashAlgorithmType.Sha3Shake256, length); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Compute.cs b/OnixLabs.Security.Cryptography/Hash.Compute.cs index 773cd8a..f70848d 100644 --- a/OnixLabs.Security.Cryptography/Hash.Compute.cs +++ b/OnixLabs.Security.Cryptography/Hash.Compute.cs @@ -1,96 +1,145 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.IO; using System.Security.Cryptography; using System.Text; +using System.Threading; +using System.Threading.Tasks; namespace OnixLabs.Security.Cryptography; public readonly partial struct Hash { /// - /// Computes the hash of the specified value using the specified . + /// Computes the hash of the specified data, using the specified . /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// Returns a representing a hash of the specified value. - public static Hash ComputeHash(string value, HashAlgorithmType type) + /// The which will be used to compute the hash. + /// The data from which to compute a hash. + /// Returns a cryptographic hash of the specified data. + public static Hash Compute(HashAlgorithm algorithm, byte[] data) { - return ComputeHash(value, type, Encoding.Default); + byte[] value = algorithm.ComputeHash(data); + return new Hash(value); } /// - /// Computes the hash of the specified value using the specified . + /// Computes the hash of the specified data, using the specified . /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a representing a hash of the specified value. - public static Hash ComputeHash(string value, HashAlgorithmType type, Encoding encoding) + /// The which will be used to compute the hash. + /// The data from which to compute a hash. + /// The number of rounds that the input data should be hashed. + /// Returns a cryptographic hash of the specified data. + public static Hash Compute(HashAlgorithm algorithm, byte[] data, int rounds) { - return ComputeHash(encoding.GetBytes(value), type); + byte[] value = algorithm.ComputeHash(data, rounds); + return new Hash(value); } /// - /// Computes the hash of the specified value using the specified . + /// Computes the hash of the specified data, using the specified . /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The output length of the computed hash in bytes. - /// Returns a representing a hash of the specified value. - public static Hash ComputeHash(string value, HashAlgorithmType type, int length) + /// The which will be used to compute the hash. + /// The data from which to compute a hash. + /// The offset into the from which to begin using data. + /// The number of bytes in the array to use as data. + /// Returns a cryptographic hash of the specified data. + public static Hash Compute(HashAlgorithm algorithm, byte[] data, int offset, int count) { - return ComputeHash(value, type, Encoding.Default, length); + byte[] value = algorithm.ComputeHash(data, offset, count); + return new Hash(value); } /// - /// Computes the hash of the specified value using the specified . + /// Computes the hash of the specified data, using the specified . /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The encoding which will be used to convert the input string into a byte array. - /// The output length of the computed hash in bytes. - /// Returns a representing a hash of the specified value. - public static Hash ComputeHash(string value, HashAlgorithmType type, Encoding encoding, int length) + /// The which will be used to compute the hash. + /// The data from which to compute a hash. + /// The offset into the from which to begin using data. + /// The number of bytes in the array to use as data. + /// The number of rounds that the input data should be hashed. + /// Returns a cryptographic hash of the specified data. + public static Hash Compute(HashAlgorithm algorithm, byte[] data, int offset, int count, int rounds) { - return ComputeHash(encoding.GetBytes(value), type, length); + byte[] value = algorithm.ComputeHash(data, offset, count, rounds); + return new Hash(value); } /// - /// Computes the hash of the specified value using the specified . + /// Computes the hash of the specified , using the specified . /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// Returns a representing a hash of the specified value. - public static Hash ComputeHash(byte[] value, HashAlgorithmType type) + /// The which will be used to compute the hash. + /// The data from which to compute a hash. + /// Returns a cryptographic hash of the specified data. + public static Hash Compute(HashAlgorithm algorithm, Stream stream) { - using HashAlgorithm algorithm = type.GetHashAlgorithm(); - byte[] hashedValue = algorithm.ComputeHash(value); - return Create(hashedValue, type); + byte[] value = algorithm.ComputeHash(stream); + return new Hash(value); } /// - /// Computes the hash of the specified value using the specified . + /// Computes the hash of the specified , using the specified . /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The output length of the computed hash in bytes. - /// Returns a representing a hash of the specified value. - public static Hash ComputeHash(byte[] value, HashAlgorithmType type, int length) + /// The which will be used to compute the hash. + /// The data from which to compute a hash. + /// The number of rounds that the input data should be hashed. + /// Returns a cryptographic hash of the specified data. + public static Hash Compute(HashAlgorithm algorithm, Stream stream, int rounds) { - using HashAlgorithm algorithm = type.GetHashAlgorithm(length); - byte[] hashedValue = algorithm.ComputeHash(value); - return Create(hashedValue, type); + byte[] value = algorithm.ComputeHash(stream, rounds); + return new Hash(value); + } + + /// + /// Computes the hash value for the specified . + /// + /// The which will be used to compute a hash value. + /// The input data to compute the hash for. + /// The which will be used to convert the specified . + /// The number of rounds that the input data should be hashed. + /// Returns a cryptographic hash of the specified data. + public static Hash Compute(HashAlgorithm algorithm, ReadOnlySpan data, Encoding? encoding = null, int rounds = 1) + { + byte[] value = algorithm.ComputeHash(data, encoding, rounds); + return new Hash(value); + } + + /// + /// Asynchronously computes the hash of the specified data, using the specified . + /// + /// The which will be used to compute the hash. + /// The data from which to compute a hash. + /// The token to monitor for cancellation requests. + /// Returns a cryptographic hash of the specified data. + public static async Task ComputeAsync(HashAlgorithm algorithm, Stream stream, CancellationToken token = default) + { + byte[] value = await algorithm.ComputeHashAsync(stream, token); + return new Hash(value); + } + + /// + /// Asynchronously computes the hash of the specified data, using the specified . + /// + /// The which will be used to compute the hash. + /// The data from which to compute a hash. + /// The number of rounds that the input data should be hashed. + /// The token to monitor for cancellation requests. + /// Returns a cryptographic hash of the specified data. + public static async Task ComputeAsync(HashAlgorithm algorithm, Stream stream, int rounds, CancellationToken token = default) + { + byte[] value = await algorithm.ComputeHashAsync(stream, rounds, token); + return new Hash(value); } } diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs deleted file mode 100644 index 2bddadd..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Md5Hash.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes an MD5 hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeMd5HashAsync(string value) - { - return await ComputeMd5HashAsync(value, Encoding.Default); - } - - /// - /// Computes an MD5 hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeMd5HashAsync(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Md5Hash, encoding); - } - - /// - /// Computes an MD5 hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeMd5HashAsync(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Md5Hash); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs deleted file mode 100644 index 5adbaff..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha1Hash.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-1 hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha1HashAsync(string value) - { - return await ComputeSha1HashAsync(value, Encoding.Default); - } - - /// - /// Computes a SHA-1 hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeSha1HashAsync(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha1Hash, encoding); - } - - /// - /// Computes a SHA-1 hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha1HashAsync(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha1Hash); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs deleted file mode 100644 index 8d20153..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash256.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-2 256-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha2Hash256Async(string value) - { - return await ComputeSha2Hash256Async(value, Encoding.Default); - } - - /// - /// Computes a SHA-2 256-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeSha2Hash256Async(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha2Hash256, encoding); - } - - /// - /// Computes a SHA-2 256-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha2Hash256Async(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha2Hash256); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs deleted file mode 100644 index 2ca6731..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash384.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-2 384-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha2Hash384Async(string value) - { - return await ComputeSha2Hash384Async(value, Encoding.Default); - } - - /// - /// Computes a SHA-2 384-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeSha2Hash384Async(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha2Hash384, encoding); - } - - /// - /// Computes a SHA-2 384-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha2Hash384Async(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha2Hash384); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs deleted file mode 100644 index fd78293..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha2Hash512.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-2 512-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha2Hash512Async(string value) - { - return await ComputeSha2Hash512Async(value, Encoding.Default); - } - - /// - /// Computes a SHA-2 512-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeSha2Hash512Async(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha2Hash512, encoding); - } - - /// - /// Computes a SHA-2 512-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha2Hash512Async(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha2Hash512); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs deleted file mode 100644 index 34c8cba..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash224.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 224-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha3Hash224Async(string value) - { - return await ComputeSha3Hash224Async(value, Encoding.Default); - } - - /// - /// Computes a SHA-3 224-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeSha3Hash224Async(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Hash224, encoding); - } - - /// - /// Computes a SHA-3 224-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha3Hash224Async(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Hash224); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs deleted file mode 100644 index 0c8e6f0..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash256.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 256-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha3Hash256Async(string value) - { - return await ComputeSha3Hash256Async(value, Encoding.Default); - } - - /// - /// Computes a SHA-3 256-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeSha3Hash256Async(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Hash256, encoding); - } - - /// - /// Computes a SHA-3 256-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha3Hash256Async(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Hash256); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs deleted file mode 100644 index b91538e..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash384.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 384-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha3Hash384Async(string value) - { - return await ComputeSha3Hash384Async(value, Encoding.Default); - } - - /// - /// Computes a SHA-3 384-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeSha3Hash384Async(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Hash384, encoding); - } - - /// - /// Computes a SHA-3 384-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha3Hash384Async(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Hash384); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs deleted file mode 100644 index f6f0bf9..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Hash512.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 512-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha3Hash512Async(string value) - { - return await ComputeSha3Hash512Async(value, Encoding.Default); - } - - /// - /// Computes a SHA-3 512-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a of the input value. - public static async Task ComputeSha3Hash512Async(string value, Encoding encoding) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Hash512, encoding); - } - - /// - /// Computes a SHA-3 512-bit hash from the specified value. - /// - /// The input value to hash. - /// Returns a of the input value. - public static async Task ComputeSha3Hash512Async(byte[] value) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Hash512); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs deleted file mode 100644 index aa62839..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake128.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 Shake 128-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static async Task ComputeSha3Shake128Async(string value, int length) - { - return await ComputeSha3Shake128Async(value, Encoding.Default, length); - } - - /// - /// Computes a SHA-3 Shake 128-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static async Task ComputeSha3Shake128Async(string value, Encoding encoding, int length) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Shake128, encoding, length); - } - - /// - /// Computes a SHA-3 Shake 128-bit hash from the specified value. - /// - /// The input value to hash. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static async Task ComputeSha3Shake128Async(byte[] value, int length) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Shake128, length); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs deleted file mode 100644 index d1154b7..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.Sha3Shake256.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a SHA-3 Shake 256-bit hash from the specified value. - /// This will use the default encoding to convert the input string into a byte array. - /// - /// The input value to hash. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static async Task ComputeSha3Shake256Async(string value, int length) - { - return await ComputeSha3Shake256Async(value, Encoding.Default, length); - } - - /// - /// Computes a SHA-3 Shake 256-bit hash from the specified value. - /// - /// The input value to hash. - /// The encoding which will be used to convert the input string into a byte array. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static async Task ComputeSha3Shake256Async(string value, Encoding encoding, int length) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Shake256, encoding, length); - } - - /// - /// Computes a SHA-3 Shake 256-bit hash from the specified value. - /// - /// The input value to hash. - /// The length of the hash in bytes. - /// Returns a of the input value. - public static async Task ComputeSha3Shake256Async(byte[] value, int length) - { - return await ComputeHashAsync(value, HashAlgorithmType.Sha3Shake256, length); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs b/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs deleted file mode 100644 index 5855f09..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeAsync.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.IO; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes the hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// Returns a representing a hash of the specified value. - public static async Task ComputeHashAsync(string value, HashAlgorithmType type) - { - return await ComputeHashAsync(value, type, Encoding.Default); - } - - /// - /// Computes the hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a representing a hash of the specified value. - public static async Task ComputeHashAsync(string value, HashAlgorithmType type, Encoding encoding) - { - return await ComputeHashAsync(encoding.GetBytes(value), type); - } - - /// - /// Computes the hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The output length of the computed hash in bytes. - /// Returns a representing a hash of the specified value. - public static async Task ComputeHashAsync(string value, HashAlgorithmType type, int length) - { - return await ComputeHashAsync(value, type, Encoding.Default, length); - } - - /// - /// Computes the hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The encoding which will be used to convert the input string into a byte array. - /// The output length of the computed hash in bytes. - /// Returns a representing a hash of the specified value. - public static async Task ComputeHashAsync(string value, HashAlgorithmType type, Encoding encoding, int length) - { - return await ComputeHashAsync(encoding.GetBytes(value), type, length); - } - - /// - /// Computes the hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// Returns a representing a hash of the specified value. - public static async Task ComputeHashAsync(byte[] value, HashAlgorithmType type) - { - using HashAlgorithm algorithm = type.GetHashAlgorithm(); - await using Stream stream = new MemoryStream(value); - byte[] hashedValue = await algorithm.ComputeHashAsync(stream); - return Create(hashedValue, type); - } - - /// - /// Computes the hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The output length of the computed hash in bytes. - /// Returns a representing a hash of the specified value. - public static async Task ComputeHashAsync(byte[] value, HashAlgorithmType type, int length) - { - using HashAlgorithm algorithm = type.GetHashAlgorithm(length); - await using Stream stream = new MemoryStream(value); - byte[] hashedValue = await algorithm.ComputeHashAsync(stream); - return Create(hashedValue, type); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs b/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs deleted file mode 100644 index 1ae41ad..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeTwice.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Security.Cryptography; -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// Returns a representing a twice-hashed hash of the specified value. - public static Hash ComputeHashTwice(string value, HashAlgorithmType type) - { - return ComputeHashTwice(value, type, Encoding.Default); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a representing a twice-hashed hash of the specified value. - public static Hash ComputeHashTwice(string value, HashAlgorithmType type, Encoding encoding) - { - return ComputeHashTwice(encoding.GetBytes(value), type); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The output length of the computed hash in bytes. - /// Returns a representing a twice-hashed hash of the specified value. - public static Hash ComputeHashTwice(string value, HashAlgorithmType type, int length) - { - return ComputeHashTwice(value, type, Encoding.Default, length); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The encoding which will be used to convert the input string into a byte array. - /// The output length of the computed hash in bytes. - /// Returns a representing a twice-hashed hash of the specified value. - public static Hash ComputeHashTwice(string value, HashAlgorithmType type, Encoding encoding, int length) - { - return ComputeHashTwice(encoding.GetBytes(value), type, length); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// Returns a representing a twice-hashed hash of the specified value. - public static Hash ComputeHashTwice(byte[] value, HashAlgorithmType type) - { - using HashAlgorithm algorithm = type.GetHashAlgorithm(); - byte[] firstRoundValue = algorithm.ComputeHash(value); - byte[] secondRoundValue = algorithm.ComputeHash(firstRoundValue); - return Create(secondRoundValue, type); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The output length of the computed hash in bytes. - /// Returns a representing a twice-hashed hash of the specified value. - public static Hash ComputeHashTwice(byte[] value, HashAlgorithmType type, int length) - { - using HashAlgorithm algorithm = type.GetHashAlgorithm(length); - byte[] firstRoundValue = algorithm.ComputeHash(value); - byte[] secondRoundValue = algorithm.ComputeHash(firstRoundValue); - return Create(secondRoundValue, type); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs b/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs deleted file mode 100644 index bd727e5..0000000 --- a/OnixLabs.Security.Cryptography/Hash.ComputeTwiceAsync.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.IO; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// Returns a representing a twice-hashed hash of the specified value. - public static async Task ComputeHashTwiceAsync(string value, HashAlgorithmType type) - { - return await ComputeHashTwiceAsync(value, type, Encoding.Default); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The encoding which will be used to convert the input string into a byte array. - /// Returns a representing a twice-hashed hash of the specified value. - public static async Task ComputeHashTwiceAsync(string value, HashAlgorithmType type, Encoding encoding) - { - return await ComputeHashTwiceAsync(encoding.GetBytes(value), type); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The output length of the computed hash in bytes. - /// Returns a representing a twice-hashed hash of the specified value. - public static async Task ComputeHashTwiceAsync(string value, HashAlgorithmType type, int length) - { - return await ComputeHashTwiceAsync(value, type, Encoding.Default, length); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The encoding which will be used to convert the input string into a byte array. - /// The output length of the computed hash in bytes. - /// Returns a representing a twice-hashed hash of the specified value. - public static async Task ComputeHashTwiceAsync(string value, HashAlgorithmType type, Encoding encoding, int length) - { - return await ComputeHashTwiceAsync(encoding.GetBytes(value), type, length); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// Returns a representing a twice-hashed hash of the specified value. - public static async Task ComputeHashTwiceAsync(byte[] value, HashAlgorithmType type) - { - using HashAlgorithm algorithm = type.GetHashAlgorithm(); - - await using Stream firstRoundStream = new MemoryStream(value); - byte[] firstRoundValue = await algorithm.ComputeHashAsync(firstRoundStream); - - await using Stream secondRoundStream = new MemoryStream(firstRoundValue); - byte[] secondRoundValue = await algorithm.ComputeHashAsync(secondRoundStream); - - return Create(secondRoundValue, type); - } - - /// - /// Computes a twice-hashed hash of the specified value using the specified . - /// - /// The value for which to compute a hash. - /// The hash algorithm type of the computed hash. - /// The output length of the computed hash in bytes. - /// Returns a representing a twice-hashed hash of the specified value. - public static async Task ComputeHashTwiceAsync(byte[] value, HashAlgorithmType type, int length) - { - using HashAlgorithm algorithm = type.GetHashAlgorithm(length); - - await using Stream firstRoundStream = new MemoryStream(value); - byte[] firstRoundValue = await algorithm.ComputeHashAsync(firstRoundStream); - - await using Stream secondRoundStream = new MemoryStream(firstRoundValue); - byte[] secondRoundValue = await algorithm.ComputeHashAsync(secondRoundStream); - - return Create(secondRoundValue, type); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Concantenate.cs b/OnixLabs.Security.Cryptography/Hash.Concantenate.cs deleted file mode 100644 index 3027936..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Concantenate.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Linq; -using System.Security.Cryptography; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Concatenates two hashes. - /// - /// The first to concatenate. - /// The second to concatenate. - /// Returns the concatenation of the two instances. - public static Hash Concatenate(Hash a, Hash b) - { - Require(a.AlgorithmType == b.AlgorithmType, "Cannot concatenate hashes of different algorithm types."); - using HashAlgorithm algorithm = a.AlgorithmType.GetHashAlgorithm(); - byte[] concatenatedValue = a.ToByteArray().Concat(b.ToByteArray()).ToArray(); - byte[] hashedValue = algorithm.ComputeHash(concatenatedValue); - return Create(hashedValue, a.AlgorithmType); - } - - /// - /// Concatenates two hashes. - /// - /// The first to concatenate. - /// The second to concatenate. - /// The length of the hash in bytes. - /// Returns the concatenation of the two instances. - public static Hash Concatenate(Hash a, Hash b, int length) - { - Require(a.AlgorithmType == b.AlgorithmType, "Cannot concatenate hashes of different algorithm types."); - using HashAlgorithm algorithm = a.AlgorithmType.GetHashAlgorithm(length); - byte[] concatenatedValue = a.ToByteArray().Concat(b.ToByteArray()).ToArray(); - byte[] hashedValue = algorithm.ComputeHash(concatenatedValue); - return Create(hashedValue, a.AlgorithmType); - } - - /// - /// Concatenates this hash with another hash. - /// - /// The other hash to concatenate with this hash. - /// Returns the concatenation of the two instances. - public Hash Concatenate(Hash other) - { - return Concatenate(this, other); - } - - /// - /// Concatenates this hash with another hash. - /// - /// The other hash to concatenate with this hash. - /// The length of the hash in bytes. - /// Returns the concatenation of the two instances. - public Hash Concatenate(Hash other, int length) - { - return Concatenate(this, other, length); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Concatenate.cs b/OnixLabs.Security.Cryptography/Hash.Concatenate.cs new file mode 100644 index 0000000..96f32bd --- /dev/null +++ b/OnixLabs.Security.Cryptography/Hash.Concatenate.cs @@ -0,0 +1,46 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Security.Cryptography; +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography; + +public readonly partial struct Hash +{ + /// + /// Concatenates the left-hand and right-hand hashes using the specified hash algorithm. + /// + /// The which will be used to compute the hash. + /// The left-hand hash to concatenate. + /// The right-hand hash to concatenate. + /// Returns a cryptographic hash representing the concatenation of the left-hand and right-hand hash values. + public static Hash Concatenate(HashAlgorithm algorithm, Hash left, Hash right) + { + byte[] data = left.ToByteArray().ConcatenateWith(right.ToByteArray()); + byte[] hash = algorithm.ComputeHash(data); + return new Hash(hash); + } + + /// + /// Concatenates the left-hand and right-hand hashes using the specified hash algorithm. + /// + /// The which will be used to compute the hash. + /// The other hash to concatenate with the current hash. + /// Returns a cryptographic hash representing the concatenation of the left-hand and right-hand hash values. + public Hash Concatenate(HashAlgorithm algorithm, Hash other) + { + return Concatenate(algorithm, this, other); + } +} diff --git a/OnixLabs.Security.Cryptography/Hash.Create.cs b/OnixLabs.Security.Cryptography/Hash.Create.cs deleted file mode 100644 index d7540ac..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Create.cs +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core; -using OnixLabs.Core.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Creates a instance from a array. - /// This will create a hash of an unknown type. - /// - /// The array to represent as a hash. - /// A new instance. - public static Hash Create(byte[] value) - { - return Create(value, HashAlgorithmType.Unknown); - } - - /// - /// Creates a instance from a array. - /// - /// The array to represent as a hash. - /// The hash algorithm type of the hash. - /// A new instance. - public static Hash Create(byte[] value, HashAlgorithmType type) - { - return new Hash(value.Copy(), type); - } - - /// - /// Creates a from the specified value. - /// - /// The Base-16 from which to construct a hash value. - /// Returns an from the specified Base-16 value. - public static Hash Create(Base16 value) - { - byte[] bytes = value.ToByteArray(); - return Create(bytes); - } - - /// - /// Creates a from the specified value. - /// - /// The Base-32 from which to construct a hash value. - /// Returns an from the specified Base-32 value. - public static Hash Create(Base32 value) - { - byte[] bytes = value.ToByteArray(); - return Create(bytes); - } - - /// - /// Creates a from the specified value. - /// - /// The Base-58 from which to construct a hash value. - /// Returns an from the specified Base-58 value. - public static Hash Create(Base58 value) - { - byte[] bytes = value.ToByteArray(); - return Create(bytes); - } - - /// - /// Creates a from the specified value. - /// - /// The Base-64 from which to construct a hash value. - /// Returns an from the specified Base-64 value. - public static Hash Create(Base64 value) - { - byte[] bytes = value.ToByteArray(); - return Create(bytes); - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.Equatable.cs b/OnixLabs.Security.Cryptography/Hash.Equatable.cs index a776a17..85b449e 100644 --- a/OnixLabs.Security.Cryptography/Hash.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Hash.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,60 +12,59 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Linq; using OnixLabs.Core.Linq; namespace OnixLabs.Security.Cryptography; -public readonly partial struct Hash : IEquatable +public readonly partial struct Hash { /// - /// Checks for equality between this instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . public bool Equals(Hash other) { - return other.AlgorithmType == AlgorithmType && other.Value.SequenceEqual(Value); + return value.SequenceEqual(other.value); } /// - /// Checks for equality between this instance and another object. + /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return obj is Hash other && Equals(other); } /// - /// Serves as a hash code function for this instance. + /// Serves as a hash code function for the current instance. /// - /// A hash code for this instance. + /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(AlgorithmType, Value.GetContentHashCode()); + return value.GetContentHashCode(); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(Hash left, Hash right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(Hash left, Hash right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/Hash.Parse.cs b/OnixLabs.Security.Cryptography/Hash.Parse.cs deleted file mode 100644 index 6b8abf2..0000000 --- a/OnixLabs.Security.Cryptography/Hash.Parse.cs +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using OnixLabs.Core; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hash -{ - /// - /// Parses a hexadecimal representation of a hash into a instance. - /// - /// A that contains a hash to convert. - /// The hash algorithm type of the hash. - /// A new instance. - public static Hash Parse(string value, HashAlgorithmType? type = null) - { - HashAlgorithmType parsedType = GetParsedHashAlgorithmType(value); - byte[] parsedValue = GetParsedHashValue(value); - - if (type is not null) - { - CheckMatchingHashAlgorithms(parsedType, type); - } - - return Create(parsedValue, parsedType); - } - - /// - /// Attempts to parse a hexadecimal representation of a hash into a instance. - /// - /// A that contains a hash to convert. - /// The hash algorithm type of the hash. - /// The result if conversion was successful. - /// Returns if the hash conversion was successful; otherwise, . - public static bool TryParse(string value, HashAlgorithmType? type, out Hash hash) - { - try - { - hash = Parse(value, type); - return true; - } - catch - { - hash = default; - return false; - } - } - - /// - /// Parses a from the specified value. - /// - /// The hash value to parse. - /// Returns a from the specified value. - private static HashAlgorithmType GetParsedHashAlgorithmType(string value) - { - string defaultHashAlgorithmType = HashAlgorithmType.Unknown.Name; - string parsedType = value.SubstringBeforeFirst(':', defaultHashAlgorithmType); - return HashAlgorithmType.FromName(parsedType); - } - - /// - /// Parses a array from the specified value. - /// - /// The hash value to parse. - /// Returns a array from the specified value. - private static byte[] GetParsedHashValue(string value) - { - string parsedValue = value.SubstringAfterFirst(':'); - return Convert.FromHexString(parsedValue); - } - - /// - /// Checks that the parsed and specified instances match. - /// - /// The parsed to check. - /// The specified to check. - /// If the instances do not match. - private static void CheckMatchingHashAlgorithms(HashAlgorithmType parsed, HashAlgorithmType specified) - { - if (parsed != specified) - { - throw new InvalidOperationException( - $"The parsed hash algorithm type '{parsed}' does not match the expected hash algorithm type '{specified}'."); - } - } -} diff --git a/OnixLabs.Security.Cryptography/Hash.To.cs b/OnixLabs.Security.Cryptography/Hash.To.cs index 3513180..75d7395 100644 --- a/OnixLabs.Security.Cryptography/Hash.To.cs +++ b/OnixLabs.Security.Cryptography/Hash.To.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,72 +14,26 @@ using System; using OnixLabs.Core; -using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; public readonly partial struct Hash { /// - /// Returns a array containing the underlying hash data. + /// Gets the underlying representation of the current instance. /// - /// A array containing the underlying hash data. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { - return Value.Copy(); + return value.Copy(); } /// - /// Returns a value that represents the underlying hash data. + /// Returns a that represents the current object. /// - /// Returns a value that represents the underlying hash data. - public Base16 ToBase16() - { - return Base16.Create(Value); - } - - /// - /// Returns a value that represents the underlying hash data. - /// - /// Returns a value that represents the underlying hash data. - public Base32 ToBase32() - { - return Base32.Create(Value); - } - - /// - /// Returns a value that represents the underlying hash data. - /// - /// Returns a value that represents the underlying hash data. - public Base58 ToBase58() - { - return Base58.Create(Value); - } - - /// - /// Returns a value that represents the underlying hash data. - /// - /// Returns a value that represents the underlying hash data. - public Base64 ToBase64() - { - return Base64.Create(Value); - } - - /// - /// Returns a that represents the current object. - /// - /// A that represents the current object. + /// Returns that represents the current object. public override string ToString() { - return Convert.ToHexString(Value).ToLower(); - } - - /// - /// Returns a that represents the current object, including the hash algorithm type. - /// - /// A that represents the current object, including the hash algorithm type. - public string ToStringWithAlgorithmType() - { - return $"{AlgorithmType.Name}:{ToString()}"; + return Convert.ToHexString(value).ToLower(); } } diff --git a/OnixLabs.Security.Cryptography/Hash.cs b/OnixLabs.Security.Cryptography/Hash.cs index b346d04..5bb1b3a 100644 --- a/OnixLabs.Security.Cryptography/Hash.cs +++ b/OnixLabs.Security.Cryptography/Hash.cs @@ -1,17 +1,19 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.Linq; using OnixLabs.Core; namespace OnixLabs.Security.Cryptography; @@ -19,27 +21,17 @@ namespace OnixLabs.Security.Cryptography; /// /// Represents a cryptographic hash. /// -public readonly partial struct Hash +/// The underlying value of the cryptographic hash. +public readonly partial struct Hash(ReadOnlySpan value) : ICryptoPrimitive, IValueComparable { + private readonly byte[] value = value.ToArray(); + /// /// Initializes a new instance of the struct. /// - /// The underlying hexadecimal value of the hash. - /// The hash algorithm type of the hash. - private Hash(byte[] value, HashAlgorithmType type) + /// The underlying value of the cryptographic hash. + /// The length of the cryptographic hash in bytes. + public Hash(byte value, int length) : this(Enumerable.Repeat(value, length).ToArray()) { - type.VerifyHashLength(value); - AlgorithmType = type; - Value = value.Copy(); } - - /// - /// Gets the hash algorithm type of the hash. - /// - public HashAlgorithmType AlgorithmType { get; } - - /// - /// Gets the underlying value of the hash. - /// - private byte[] Value { get; } } diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs deleted file mode 100644 index 7e79dfb..0000000 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Enumerations.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Security.Cryptography; - -public sealed partial class HashAlgorithmType -{ - /// - /// An unknown hash algorithm. - /// - public static readonly HashAlgorithmType Unknown = new(0, nameof(Unknown), UnknownLength, false); - - /// - /// The MD5 hash algorithm. - /// - public static readonly HashAlgorithmType Md5Hash = new(1, nameof(Md5Hash), 16, false); - - /// - /// The SHA-1 hash algorithm. - /// - public static readonly HashAlgorithmType Sha1Hash = new(2, nameof(Sha1Hash), 20, false); - - /// - /// The SHA-2 256-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha2Hash256 = new(3, nameof(Sha2Hash256), 32, false); - - /// - /// The SHA-2 384-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha2Hash384 = new(4, nameof(Sha2Hash384), 48, false); - - /// - /// The SHA-2 512-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha2Hash512 = new(5, nameof(Sha2Hash512), 64, false); - - /// - /// The SHA-3 224-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha3Hash224 = new(6, nameof(Sha3Hash224), 28, false); - - /// - /// The SHA-3 256-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha3Hash256 = new(7, nameof(Sha3Hash256), 32, false); - - /// - /// The SHA-3 384-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha3Hash384 = new(8, nameof(Sha3Hash384), 48, false); - - /// - /// The SHA-3 512-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha3Hash512 = new(9, nameof(Sha3Hash512), 64, false); - - /// - /// The SHA-3 Shake 128-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha3Shake128 = new(10, nameof(Sha3Shake128), UnknownLength, false); - - /// - /// The SHA-3 Shake 256-bit hash algorithm. - /// - public static readonly HashAlgorithmType Sha3Shake256 = new(11, nameof(Sha3Shake256), UnknownLength, false); - - /// - /// The MD5 HMAC keyed hash algorithm. - /// - public static readonly HashAlgorithmType Md5Hmac = new(12, nameof(Md5Hmac), 16, true); - - /// - /// The SHA-1 HMAC keyed hash algorithm. - /// - public static readonly HashAlgorithmType Sha1Hmac = new(13, nameof(Sha1Hmac), 20, true); - - /// - /// The SHA-2 256-bit HMAC keyed hash algorithm. - /// - public static readonly HashAlgorithmType Sha2Hmac256 = new(14, nameof(Sha2Hmac256), 32, true); - - /// - /// The SHA-2 384-bit HMAC keyed hash algorithm. - /// - public static readonly HashAlgorithmType Sha2Hmac384 = new(15, nameof(Sha2Hmac384), 48, true); - - /// - /// The SHA-2 512-bit HMAC keyed hash algorithm. - /// - public static readonly HashAlgorithmType Sha2Hmac512 = new(16, nameof(Sha2Hmac512), 64, true); -} diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs deleted file mode 100644 index 04419ae..0000000 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Get.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Security.Cryptography; - -namespace OnixLabs.Security.Cryptography; - -public sealed partial class HashAlgorithmType -{ - /// - /// Gets the hash algorithm for this instance. - /// - /// Returns a for this . - public HashAlgorithm GetHashAlgorithm() - { - return GetHashAlgorithm(Length); - } - - /// - /// Gets the hash algorithm for this instance. - /// - /// Specifies the expected output hash length. - /// Returns a for this . - /// If the hash algorithm does not expect an output length. - /// If the hash algorithm is unknown. - public HashAlgorithm GetHashAlgorithm(int length) - { - Require(IsUnknown || length == Length, $"Output length not expected for the specified hash algorithm: {Name}", nameof(length)); - - return Name switch - { - nameof(Md5Hash) => MD5.Create(), - nameof(Sha1Hash) => SHA1.Create(), - nameof(Sha2Hash256) => SHA256.Create(), - nameof(Sha2Hash384) => SHA384.Create(), - nameof(Sha2Hash512) => SHA512.Create(), - nameof(Sha3Hash224) => Sha3.CreateSha3Hash224(), - nameof(Sha3Hash256) => Sha3.CreateSha3Hash256(), - nameof(Sha3Hash384) => Sha3.CreateSha3Hash384(), - nameof(Sha3Hash512) => Sha3.CreateSha3Hash512(), - nameof(Sha3Shake128) => Sha3.CreateSha3Shake128(length), - nameof(Sha3Shake256) => Sha3.CreateSha3Shake256(length), - _ => throw new ArgumentException($"Hash algorithm '{Name}' is unknown.") - }; - } - - /// - /// Gets the keyed hash algorithm for this instance. - /// - /// The key that should be used by the keyed hash algorithm. - /// Returns a for this . - /// If the hash algorithm is unknown or is not a keyed hash algorithm. - public KeyedHashAlgorithm GetKeyedHashAlgorithm(byte[]? key = null) - { - Check(IsKeyBased, $"Hash algorithm type '{Name}' is not a keyed hash algorithm."); - - return Name switch - { - nameof(Md5Hmac) => key is null ? new HMACMD5() : new HMACMD5(key), - nameof(Sha1Hmac) => key is null ? new HMACSHA1() : new HMACSHA1(key), - nameof(Sha2Hmac256) => key is null ? new HMACSHA256() : new HMACSHA256(key), - nameof(Sha2Hmac384) => key is null ? new HMACSHA384() : new HMACSHA384(key), - nameof(Sha2Hmac512) => key is null ? new HMACSHA512() : new HMACSHA512(key), - _ => throw new ArgumentException($"Hash algorithm '{Name}' is unknown.") - }; - } - - /// - /// Gets the equivalent for this . - /// - /// Returns the equivalent for this . - /// If there is no corresponding equivalent for this . - public HashAlgorithmName GetHashAlgorithmName() - { - return Name switch - { - nameof(Md5Hash) => HashAlgorithmName.MD5, - nameof(Sha1Hash) => HashAlgorithmName.SHA1, - nameof(Sha2Hash256) => HashAlgorithmName.SHA256, - nameof(Sha2Hash384) => HashAlgorithmName.SHA384, - nameof(Sha2Hash512) => HashAlgorithmName.SHA512, - _ => throw new ArgumentException($"No corresponding {nameof(HashAlgorithmName)} for '{Name}'.") - }; - } -} diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs deleted file mode 100644 index 1ce87d1..0000000 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.Verify.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Security.Cryptography; - -public sealed partial class HashAlgorithmType -{ - /// - /// Determines whether the length of a byte array is valid. - /// - /// The byte array to length check. - /// Returns if the length of the byte array is valid; otherwise, . - public bool IsValidHashLength(byte[] value) - { - return Length == -1 || Length == value.Length; - } - - /// - /// Verifies that the length of a byte array is valid. - /// - /// The byte array to length check. - /// If the length of the byte array is invalid. - public void VerifyHashLength(byte[] value) - { - Require(IsValidHashLength(value), "The length of the hash is invalid.", nameof(value)); - } -} diff --git a/OnixLabs.Security.Cryptography/HashAlgorithmType.cs b/OnixLabs.Security.Cryptography/HashAlgorithmType.cs deleted file mode 100644 index 39df328..0000000 --- a/OnixLabs.Security.Cryptography/HashAlgorithmType.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core; - -namespace OnixLabs.Security.Cryptography; - -/// -/// Specifies values that define known hash algorithm types. -/// -public sealed partial class HashAlgorithmType : Enumeration -{ - /// - /// A constant that defines an unknown hash algorithm length. - /// - private const int UnknownLength = -1; - - /// - /// Initializes a new instance of the class. - /// - /// The value of the hash algorithm type. - /// The name of the hash algorithm type. - /// The length in bytes of the hash algorithm type. - /// Determines whether the algorithm is a key based hash algorithm. - private HashAlgorithmType(int value, string name, int length, bool isKeyBased) : base(value, name) - { - Length = length; - IsKeyBased = isKeyBased; - } - - /// - /// Gets the length of an algorithm's hash in bytes. - /// -1 Means that the algorithm's hash is of variable length, or is unknown. - /// - public int Length { get; } - - /// - /// Gets a value that determines whether the algorithm is a key based hash algorithm. - /// - public bool IsKeyBased { get; } - - /// - /// Gets a value that determines whether the algorithm type is unknown. - /// - public bool IsUnknown => ReferenceEquals(this, Unknown); -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs deleted file mode 100644 index 962a98a..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Md5Hmac.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes an MD5 HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeMd5Hmac(string value, string key) - { - return ComputeMd5Hmac(value, key, Encoding.Default); - } - - /// - /// Computes an MD5 HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static Hmac ComputeMd5Hmac(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return ComputeMd5Hmac(valueBytes, keyBytes); - } - - /// - /// Computes an MD5 HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeMd5Hmac(byte[] value, byte[] key) - { - return ComputeHmac(value, key, HashAlgorithmType.Md5Hmac); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs deleted file mode 100644 index 1c15d62..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha1Hmac.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a SHA-1 HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeSha1Hmac(string value, string key) - { - return ComputeSha1Hmac(value, key, Encoding.Default); - } - - /// - /// Computes a SHA-1 HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static Hmac ComputeSha1Hmac(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return ComputeSha1Hmac(valueBytes, keyBytes); - } - - /// - /// Computes a SHA-1 HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeSha1Hmac(byte[] value, byte[] key) - { - return ComputeHmac(value, key, HashAlgorithmType.Sha1Hmac); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs deleted file mode 100644 index 3424be3..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac256.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a SHA-2 256-bit HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac256(string value, string key) - { - return ComputeSha2Hmac256(value, key, Encoding.Default); - } - - /// - /// Computes a SHA-2 256-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac256(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return ComputeSha2Hmac256(valueBytes, keyBytes); - } - - /// - /// Computes a SHA-2 256-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac256(byte[] value, byte[] key) - { - return ComputeHmac(value, key, HashAlgorithmType.Sha2Hmac256); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs deleted file mode 100644 index ab6780d..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac384.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a SHA-2 384-bit HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac384(string value, string key) - { - return ComputeSha2Hmac384(value, key, Encoding.Default); - } - - /// - /// Computes a SHA-2 384-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac384(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return ComputeSha2Hmac384(valueBytes, keyBytes); - } - - /// - /// Computes a SHA-2 384-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac384(byte[] value, byte[] key) - { - return ComputeHmac(value, key, HashAlgorithmType.Sha2Hmac384); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs deleted file mode 100644 index 5e29f08..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.Sha2Hmac512.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a SHA-2 512-bit HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac512(string value, string key) - { - return ComputeSha2Hmac512(value, key, Encoding.Default); - } - - /// - /// Computes a SHA-2 512-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac512(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return ComputeSha2Hmac512(valueBytes, keyBytes); - } - - /// - /// Computes a SHA-2 512-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static Hmac ComputeSha2Hmac512(byte[] value, byte[] key) - { - return ComputeHmac(value, key, HashAlgorithmType.Sha2Hmac512); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Compute.cs b/OnixLabs.Security.Cryptography/Hmac.Compute.cs deleted file mode 100644 index 3ab0ea7..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Compute.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Security.Cryptography; -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a hashed message authentication code (HMAC). - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The hash algorithm type of the computed HMAC. - /// Returns a representing the specified value and key. - public static Hmac ComputeHmac(string value, string key, HashAlgorithmType type) - { - return ComputeHmac(value, key, type, Encoding.Default); - } - - /// - /// Computes a hashed message authentication code (HMAC). - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The hash algorithm type of the computed HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a representing the specified value and key. - public static Hmac ComputeHmac(string value, string key, HashAlgorithmType type, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return ComputeHmac(valueBytes, keyBytes, type); - } - - /// - /// Computes a hashed message authentication code (HMAC). - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The hash algorithm type of the computed HMAC. - /// Returns a representing the specified value and key. - public static Hmac ComputeHmac(byte[] value, byte[] key, HashAlgorithmType type) - { - using KeyedHashAlgorithm algorithm = type.GetKeyedHashAlgorithm(key); - byte[] data = algorithm.ComputeHash(value); - Hash hash = Hash.Create(data, type); - return Create(hash, value); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs deleted file mode 100644 index f5f9ffb..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Md5Hmac.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes an MD5 HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeMd5HmacAsync(string value, string key) - { - return await ComputeMd5HmacAsync(value, key, Encoding.Default); - } - - /// - /// Computes an MD5 HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static async Task ComputeMd5HmacAsync(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return await ComputeMd5HmacAsync(valueBytes, keyBytes); - } - - /// - /// Computes an MD5 HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeMd5HmacAsync(byte[] value, byte[] key) - { - return await ComputeHmacAsync(value, key, HashAlgorithmType.Md5Hmac); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs deleted file mode 100644 index f2f3333..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha1Hmac.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a SHA-1 HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeSha1HmacAsync(string value, string key) - { - return await ComputeSha1HmacAsync(value, key, Encoding.Default); - } - - /// - /// Computes a SHA-1 HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static async Task ComputeSha1HmacAsync(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return await ComputeSha1HmacAsync(valueBytes, keyBytes); - } - - /// - /// Computes a SHA-1 HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeSha1HmacAsync(byte[] value, byte[] key) - { - return await ComputeHmacAsync(value, key, HashAlgorithmType.Sha1Hmac); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs deleted file mode 100644 index 29c24ab..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac256.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a SHA-2 256-bit HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac256Async(string value, string key) - { - return await ComputeSha2Hmac256Async(value, key, Encoding.Default); - } - - /// - /// Computes a SHA-2 256-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac256Async(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return await ComputeSha2Hmac256Async(valueBytes, keyBytes); - } - - /// - /// Computes a SHA-2 256-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac256Async(byte[] value, byte[] key) - { - return await ComputeHmacAsync(value, key, HashAlgorithmType.Sha2Hmac256); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs deleted file mode 100644 index af81aae..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac384.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a SHA-2 384-bit HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac384Async(string value, string key) - { - return await ComputeSha2Hmac384Async(value, key, Encoding.Default); - } - - /// - /// Computes a SHA-2 384-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac384Async(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return await ComputeSha2Hmac384Async(valueBytes, keyBytes); - } - - /// - /// Computes a SHA-2 384-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac384Async(byte[] value, byte[] key) - { - return await ComputeHmacAsync(value, key, HashAlgorithmType.Sha2Hmac384); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs deleted file mode 100644 index 0a022fe..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.Sha2Hmac512.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a SHA-2 512-bit HMAC from the specified value and key. - /// This will use the default encoding to convert the input value and key into a byte array. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac512Async(string value, string key) - { - return await ComputeSha2Hmac512Async(value, key, Encoding.Default); - } - - /// - /// Computes a SHA-2 512-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac512Async(string value, string key, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return await ComputeSha2Hmac512Async(valueBytes, keyBytes); - } - - /// - /// Computes a SHA-2 512-bit HMAC from the specified value and key. - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// Returns a of the input value and key. - public static async Task ComputeSha2Hmac512Async(byte[] value, byte[] key) - { - return await ComputeHmacAsync(value, key, HashAlgorithmType.Sha2Hmac512); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs b/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs deleted file mode 100644 index 5fd31ec..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.ComputeAsync.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.IO; -using System.Security.Cryptography; -using System.Text; -using System.Threading.Tasks; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Computes a hashed message authentication code (HMAC). - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The hash algorithm type of the computed HMAC. - /// Returns a representing the specified value and key. - public static async Task ComputeHmacAsync(string value, string key, HashAlgorithmType type) - { - return await ComputeHmacAsync(value, key, type, Encoding.Default); - } - - /// - /// Computes a hashed message authentication code (HMAC). - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The hash algorithm type of the computed HMAC. - /// The encoding which will be used to convert the value and key into a byte array. - /// Returns a representing the specified value and key. - public static async Task ComputeHmacAsync(string value, string key, HashAlgorithmType type, Encoding encoding) - { - byte[] valueBytes = encoding.GetBytes(value); - byte[] keyBytes = encoding.GetBytes(key); - return await ComputeHmacAsync(valueBytes, keyBytes, type); - } - - /// - /// Computes a hashed message authentication code (HMAC). - /// - /// The value for which to compute a HMAC. - /// The key for which to compute a HMAC. - /// The hash algorithm type of the computed HMAC. - /// Returns a representing the specified value and key. - public static async Task ComputeHmacAsync(byte[] value, byte[] key, HashAlgorithmType type) - { - using KeyedHashAlgorithm algorithm = type.GetKeyedHashAlgorithm(key); - await using Stream stream = new MemoryStream(value); - - byte[] data = await algorithm.ComputeHashAsync(stream); - Hash hash = Hash.Create(data, type); - - return Create(hash, value); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Create.cs b/OnixLabs.Security.Cryptography/Hmac.Create.cs deleted file mode 100644 index ed1f1de..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Create.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Creates a hashed message authentication code (HMAC). - /// - /// The representing the HMAC. - /// The underlying un-hashed data. - /// Returns a new instance. - public static Hmac Create(Hash hash, byte[] data) - { - return new Hmac(hash, data.Copy()); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs b/OnixLabs.Security.Cryptography/Hmac.Equatable.cs deleted file mode 100644 index 303724f..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Equatable.cs +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using System.Linq; -using OnixLabs.Core.Linq; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac : IEquatable -{ - /// - /// Checks for equality between this instance and another object. - /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public bool Equals(Hmac other) - { - return other.Hash == Hash && other.Data.SequenceEqual(Data); - } - - /// - /// Checks for equality between this instance and another object. - /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public override bool Equals(object? obj) - { - return obj is Hmac other && Equals(other); - } - - /// - /// Serves as a hash code function for this instance. - /// - /// A hash code for this instance. - public override int GetHashCode() - { - return HashCode.Combine(Hash, Data.GetContentHashCode()); - } - - /// - /// Performs an equality check between two object instances. - /// - /// The left-hand instance to compare. - /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, . - public static bool operator ==(Hmac left, Hmac right) - { - return Equals(left, right); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// The left-hand instance to compare. - /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, . - public static bool operator !=(Hmac left, Hmac right) - { - return !Equals(left, right); - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Parse.cs b/OnixLabs.Security.Cryptography/Hmac.Parse.cs deleted file mode 100644 index 6588073..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Parse.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; -using OnixLabs.Core; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Parses a hexadecimal representation of a HMAC into a instance. - /// - /// A that contains a HMAC to convert. - /// The hash algorithm type of the HMAC. - /// A new instance. - public static Hmac Parse(string value, HashAlgorithmType? type = null) - { - string hashComponent = value.SubstringBeforeLast(':'); - string dataComponent = value.SubstringAfterLast(':'); - - Hash hash = Hash.Parse(hashComponent, type); - byte[] data = Convert.FromHexString(dataComponent); - - return Create(hash, data); - } - - /// - /// Attempts to parse a hexadecimal representation of a HMAC into a instance. - /// - /// A that contains a HMAC to convert. - /// The hash algorithm type of the hash. - /// The result if conversion was successful. - /// Returns if the hash conversion was successful; otherwise, . - public static bool TryParse(string value, HashAlgorithmType? type, out Hmac hmac) - { - try - { - hmac = Parse(value, type); - return true; - } - catch - { - hmac = default; - return false; - } - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.To.cs b/OnixLabs.Security.Cryptography/Hmac.To.cs deleted file mode 100644 index aa47272..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.To.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Returns a that represents the current object. - /// - /// A that represents the current object. - public override string ToString() - { - return $"{Hash}:{Convert.ToHexString(Data).ToLower()}"; - } - - /// - /// Returns a that represents the current object, including the hash algorithm type. - /// - /// A that represents the current object, including the hash algorithm type. - public string ToStringWithAlgorithmType() - { - return $"{Hash.AlgorithmType.Name}:{ToString()}"; - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Verify.cs b/OnixLabs.Security.Cryptography/Hmac.Verify.cs deleted file mode 100644 index baf4345..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.Verify.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Security.Cryptography; -using System.Text; - -namespace OnixLabs.Security.Cryptography; - -public readonly partial struct Hmac -{ - /// - /// Determines whether the hashed message authentication code (HMAC) was created with the specified key. - /// - /// The key to validate against this . - /// Returns if this was created with the specified key; otherwise, . - public bool IsValid(string key) - { - return IsValid(key, Encoding.Default); - } - - /// - /// Determines whether the hashed message authentication code (HMAC) was created with the specified key. - /// - /// The key to validate against this . - /// The encoding which will be used to convert the key into a byte array. - /// Returns if this was created with the specified key; otherwise, . - public bool IsValid(string key, Encoding encoding) - { - byte[] keyBytes = encoding.GetBytes(key); - return IsValid(keyBytes); - } - - /// - /// Determines whether the hashed message authentication code (HMAC) was created with the specified key. - /// - /// The key to validate against this . - /// Returns if this was created with the specified key; otherwise, . - public bool IsValid(byte[] key) - { - return this == ComputeHmac(Data, key, Hash.AlgorithmType); - } - - /// - /// Verifies that the hashed message authentication code (HMAC) was created with the specified key. - /// - /// The key to validate against this . - public void Verify(string key) - { - Verify(key, Encoding.Default); - } - - /// - /// Verifies that the hashed message authentication code (HMAC) was created with the specified key. - /// - /// The encoding which will be used to convert the key into a byte array. - /// The key to validate against this . - public void Verify(string key, Encoding encoding) - { - byte[] keyBytes = encoding.GetBytes(key); - Verify(keyBytes); - } - - /// - /// Verifies that the hashed message authentication code (HMAC) was created with the specified key. - /// - /// The key to validate against this . - public void Verify(byte[] key) - { - if (!IsValid(key)) - { - throw new CryptographicException("The HMAC was could not be verified with the specified key."); - } - } -} diff --git a/OnixLabs.Security.Cryptography/Hmac.cs b/OnixLabs.Security.Cryptography/Hmac.cs deleted file mode 100644 index 7de8b96..0000000 --- a/OnixLabs.Security.Cryptography/Hmac.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using OnixLabs.Core; - -namespace OnixLabs.Security.Cryptography; - -/// -/// Represents a hashed message authentication code (HMAC). -/// -public readonly partial struct Hmac -{ - /// - /// Represents the underlying un-hashed data. - /// - private readonly byte[] data; - - /// - /// Initializes a new instance of the struct. - /// - /// The representing the HMAC. - /// The underlying un-hashed data. - private Hmac(Hash hash, byte[] data) - { - Hash = hash; - this.data = data.Copy(); - } - - /// - /// Gets the representing the HMAC. - /// - public Hash Hash { get; } - - /// - /// Gets the underlying un-hashed data. - /// - public byte[] Data => data.Copy(); -} diff --git a/OnixLabs.Security.Cryptography/Hmac.Constants.cs b/OnixLabs.Security.Cryptography/ICryptoPrimitive.cs similarity index 64% rename from OnixLabs.Security.Cryptography/Hmac.Constants.cs rename to OnixLabs.Security.Cryptography/ICryptoPrimitive.cs index e75bf8a..3dec14f 100644 --- a/OnixLabs.Security.Cryptography/Hmac.Constants.cs +++ b/OnixLabs.Security.Cryptography/ICryptoPrimitive.cs @@ -1,23 +1,23 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using OnixLabs.Core; + namespace OnixLabs.Security.Cryptography; -public readonly partial struct Hmac -{ - /// - /// Gets an empty hashed message authentication code (HMAC) value. - /// - public static Hmac Empty => Create(Hash.Empty, EmptyArray()); -} +/// +/// Defines a cryptographic primitive. +/// +/// The underlying type of the cryptographic primitive. +public interface ICryptoPrimitive : IValueEquatable, IBinaryConvertible where T : ICryptoPrimitive; diff --git a/OnixLabs.Security.Cryptography/IEcdsaPrivateKey.cs b/OnixLabs.Security.Cryptography/IEcdsaPrivateKey.cs new file mode 100644 index 0000000..de31a28 --- /dev/null +++ b/OnixLabs.Security.Cryptography/IEcdsaPrivateKey.cs @@ -0,0 +1,170 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using System.Security.Cryptography; +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography; + +/// +/// Defines an ECDSA cryptographic private key. +/// +public interface IEcdsaPrivateKey : IBinaryConvertible +{ + /// + /// Imports the ECDSA cryptographic private key data in PKCS #8 format. + /// + /// The cryptographic private key data to import. + /// Returns a new instance from the imported cryptographic private key data. + public static abstract EcdsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data); + + /// + /// Imports the ECDSA cryptographic private key data in PKCS #8 format. + /// + /// The cryptographic private key data to import. + /// The number of bytes read from the input data. + /// Returns a new instance from the imported cryptographic private key data. + public static abstract EcdsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, out int bytesRead); + + /// + /// Imports the ECDSA cryptographic private key data in encrypted PKCS #8 format. + /// + /// The cryptographic private key data to import. + /// The password required for password based decryption. + /// Returns a new instance from the imported cryptographic private key data. + public static abstract EcdsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, ReadOnlySpan password); + + /// + /// Imports the ECDSA cryptographic private key data in encrypted PKCS #8 format. + /// + /// The cryptographic private key data to import. + /// The password required for password based decryption. + /// The number of bytes read from the input data. + /// Returns a new instance from the imported cryptographic private key data. + public static abstract EcdsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, ReadOnlySpan password, out int bytesRead); + + /// + /// Exports the ECDSA cryptographic private key data in PKCS #8 format. + /// + /// Returns a new instance containing the ECDSA cryptographic private key data in PKCS #8 format. + byte[] ExportPkcs8PrivateKey(); + + /// + /// Exports the ECDSA cryptographic private key data in encrypted PKCS #8 format. + /// + /// The password to use for encryption. + /// The parameters required for password based encryption. + /// Returns a new instance containing the ECDSA cryptographic private key data in PKCS #8 format. + byte[] ExportPkcs8PrivateKey(ReadOnlySpan password, PbeParameters parameters); + + /// + /// Gets the ECDSA cryptographic public key component from the current ECDSA cryptographic private key. + /// + /// Returns a new instance containing the ECDSA cryptographic public key component from the current ECDSA cryptographic private key. + EcdsaPublicKey GetPublicKey(); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Signs the specified . + /// + /// The hash to sign. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignHash(Hash hash, DSASignatureFormat format = default); + + /// + /// Signs the specified . + /// + /// The hash to sign. + /// The digital signature format which will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignHash(ReadOnlySpan hash, DSASignatureFormat format = default); +} diff --git a/OnixLabs.Security.Cryptography/IEcdsaPublicKey.cs b/OnixLabs.Security.Cryptography/IEcdsaPublicKey.cs new file mode 100644 index 0000000..d944840 --- /dev/null +++ b/OnixLabs.Security.Cryptography/IEcdsaPublicKey.cs @@ -0,0 +1,514 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using System.Security.Cryptography; +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography; + +/// +/// Defines an ECDSA cryptographic public key. +/// +public interface IEcdsaPublicKey : IBinaryConvertible +{ + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Determines whether the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + bool IsHashValid(ReadOnlySpan signature, Hash hash, DSASignatureFormat format = default); + + /// + /// Determines whether the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + bool IsHashValid(ReadOnlySpan signature, ReadOnlySpan hash, DSASignatureFormat format = default); + + /// + /// Determines whether the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + bool IsHashValid(DigitalSignature signature, Hash hash, DSASignatureFormat format = default); + + /// + /// Determines whether the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the ECDSA cryptographic private key that corresponds to the + /// current ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + bool IsHashValid(DigitalSignature signature, ReadOnlySpan hash, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, ReadOnlySpan data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, Stream data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, IBinaryConvertible data, HashAlgorithm algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, ReadOnlySpan data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, Stream data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified data was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned data to validate against the current ECDSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, IBinaryConvertible data, HashAlgorithmName algorithm, DSASignatureFormat format = default); + + /// + /// Verifies that the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyHash(ReadOnlySpan signature, Hash hash, DSASignatureFormat format = default); + + /// + /// Verifies that the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyHash(ReadOnlySpan signature, ReadOnlySpan hash, DSASignatureFormat format = default); + + /// + /// Verifies that the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyHash(DigitalSignature signature, Hash hash, DSASignatureFormat format = default); + + /// + /// Verifies that the specified hash was signed by the ECDSA cryptographic private key that corresponds to the current + /// ECDSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current ECDSA cryptographic public key. + /// The unsigned hash to validate against the current ECDSA cryptographic public key. + /// The digital signature format that was used to generate the cryptographic digital signature. + void VerifyHash(DigitalSignature signature, ReadOnlySpan hash, DSASignatureFormat format = default); +} diff --git a/OnixLabs.Security.Cryptography/IHashable.cs b/OnixLabs.Security.Cryptography/IHashable.cs index 48f2340..a902856 100644 --- a/OnixLabs.Security.Cryptography/IHashable.cs +++ b/OnixLabs.Security.Cryptography/IHashable.cs @@ -1,27 +1,29 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System.Security.Cryptography; + namespace OnixLabs.Security.Cryptography; /// -/// Defines a mechanism for computing the hash of a data structure. +/// Defines a mechanism for computing the of a data structure. /// public interface IHashable { /// - /// Computes the hash of the current object. + /// Computes the hash of the current object. /// - /// Return the computed hash of the current object. - Hash ComputeHash(); + /// Returns the computed hash of the current object. + Hash ComputeHash(HashAlgorithm algorithm); } diff --git a/OnixLabs.Security.Cryptography/IRsaPrivateKey.cs b/OnixLabs.Security.Cryptography/IRsaPrivateKey.cs new file mode 100644 index 0000000..476aa0b --- /dev/null +++ b/OnixLabs.Security.Cryptography/IRsaPrivateKey.cs @@ -0,0 +1,134 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using System.Security.Cryptography; +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography; + +/// +/// Defines an RSA cryptographic private key. +/// +public interface IRsaPrivateKey : IBinaryConvertible +{ + /// + /// Imports the RSA cryptographic private key data in PKCS #8 format. + /// + /// The cryptographic private key data to import. + /// Returns a new instance from the imported cryptographic private key data. + public static abstract RsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data); + + /// + /// Imports the RSA cryptographic private key data in PKCS #8 format. + /// + /// The cryptographic private key data to import. + /// The number of bytes read from the input data. + /// Returns a new instance from the imported cryptographic private key data. + public static abstract RsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, out int bytesRead); + + /// + /// Imports the RSA cryptographic private key data in encrypted PKCS #8 format. + /// + /// The cryptographic private key data to import. + /// The password required for password based decryption. + /// Returns a new instance from the imported cryptographic private key data. + public static abstract RsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, ReadOnlySpan password); + + /// + /// Imports the RSA cryptographic private key data in encrypted PKCS #8 format. + /// + /// The cryptographic private key data to import. + /// The password required for password based decryption. + /// The number of bytes read from the input data. + /// Returns a new instance from the imported cryptographic private key data. + public static abstract RsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, ReadOnlySpan password, out int bytesRead); + + /// + /// Exports the RSA cryptographic private key data in PKCS #8 format. + /// + /// Returns a new instance containing the RSA cryptographic private key data in PKCS #8 format. + byte[] ExportPkcs8PrivateKey(); + + /// + /// Exports the RSA cryptographic private key data in encrypted PKCS #8 format. + /// + /// The password to use for encryption. + /// The parameters required for password based encryption. + /// Returns a new instance containing the RSA cryptographic private key data in PKCS #8 format. + byte[] ExportPkcs8PrivateKey(ReadOnlySpan password, PbeParameters parameters); + + /// + /// Gets the RSA cryptographic public key component from the current RSA cryptographic private key. + /// + /// Returns a new instance containing the RSA cryptographic public key component from the current RSA cryptographic private key. + RsaPublicKey GetPublicKey(); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that will be used to hash the input data. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignData(IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Signs the specified . + /// + /// The hash to sign. + /// The hash algorithm that will be used to hash the input hash. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignHash(Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Signs the specified . + /// + /// The hash to sign. + /// The hash algorithm that will be used to hash the input hash. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + byte[] SignHash(ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding); +} diff --git a/OnixLabs.Security.Cryptography/IRsaPublicKey.cs b/OnixLabs.Security.Cryptography/IRsaPublicKey.cs new file mode 100644 index 0000000..81c75ae --- /dev/null +++ b/OnixLabs.Security.Cryptography/IRsaPublicKey.cs @@ -0,0 +1,322 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.IO; +using System.Security.Cryptography; +using OnixLabs.Core; + +namespace OnixLabs.Security.Cryptography; + +/// +/// Defines an RSA cryptographic public key. +/// +public interface IRsaPublicKey : IBinaryConvertible +{ + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + bool IsDataValid(DigitalSignature signature, IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + bool IsHashValid(ReadOnlySpan signature, ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + bool IsHashValid(DigitalSignature signature, ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + bool IsHashValid(ReadOnlySpan signature, Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Determines whether the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + bool IsHashValid(DigitalSignature signature, Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyData(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyData(DigitalSignature signature, IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyHash(ReadOnlySpan signature, ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyHash(DigitalSignature signature, ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyHash(ReadOnlySpan signature, Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding); + + /// + /// Verifies that the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + void VerifyHash(DigitalSignature signature, Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding); +} diff --git a/OnixLabs.Security.Cryptography/KeyPair.Create.cs b/OnixLabs.Security.Cryptography/KeyPair.Create.cs deleted file mode 100644 index fe217b8..0000000 --- a/OnixLabs.Security.Cryptography/KeyPair.Create.cs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Security.Cryptography; - -namespace OnixLabs.Security.Cryptography; - -public sealed partial class KeyPair -{ - /// - /// Creates an ECDSA public/private key pair. - /// - /// The for computing signature data. - /// Returns an ECDSA public/private key pair. - public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type) - { - using ECDsa asymmetricAlgorithm = ECDsa.Create(); - - PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type); - PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type); - - return new KeyPair(privateKey, publicKey, type); - } - - /// - /// Creates an ECDSA public/private key pair. - /// - /// The for computing signature data. - /// The curve to use for key generation. - /// Returns an ECDSA public/private key pair. - public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type, ECCurve curve) - { - using ECDsa asymmetricAlgorithm = ECDsa.Create(curve); - - PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type); - PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type); - - return new KeyPair(privateKey, publicKey, type); - } - - /// - /// Creates an ECDSA public/private key pair. - /// - /// The for computing signature data. - /// The parameters representing the key to use. - /// Returns an ECDSA public/private key pair. - public static KeyPair CreateEcdsaKeyPair(HashAlgorithmType type, ECParameters parameters) - { - using ECDsa asymmetricAlgorithm = ECDsa.Create(parameters); - - PrivateKey privateKey = new EcdsaPrivateKey(asymmetricAlgorithm.ExportECPrivateKey(), type); - PublicKey publicKey = new EcdsaPublicKey(asymmetricAlgorithm.ExportSubjectPublicKeyInfo(), type); - - return new KeyPair(privateKey, publicKey, type); - } - - /// - /// Creates an RSA public/private key pair. - /// - /// The for computing signature data. - /// The for computing signature data. - /// Returns an ECDSA public/private key pair. - public static KeyPair CreateRsaKeyPair(HashAlgorithmType type, RSASignaturePadding padding) - { - using RSA asymmetricAlgorithm = RSA.Create(); - - PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding); - PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding); - - return new KeyPair(privateKey, publicKey, type); - } - - /// - /// Creates an RSA public/private key pair. - /// - /// The for computing signature data. - /// The for computing signature data. - /// The key size, in bits. - /// Returns an ECDSA public/private key pair. - public static KeyPair CreateRsaKeyPair(HashAlgorithmType type, RSASignaturePadding padding, int keySizeInBits) - { - using RSA asymmetricAlgorithm = RSA.Create(keySizeInBits); - - PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding); - PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding); - - return new KeyPair(privateKey, publicKey, type); - } - - /// - /// Creates an RSA public/private key pair. - /// - /// The for computing signature data. - /// The for computing signature data. - /// The parameters for the RSA algorithm. - /// Returns an ECDSA public/private key pair. - public static KeyPair CreateRsaKeyPair(HashAlgorithmType type, RSASignaturePadding padding, RSAParameters parameters) - { - using RSA asymmetricAlgorithm = RSA.Create(parameters); - - PrivateKey privateKey = new RsaPrivateKey(asymmetricAlgorithm.ExportRSAPrivateKey(), type, padding); - PublicKey publicKey = new RsaPublicKey(asymmetricAlgorithm.ExportRSAPublicKey(), type, padding); - - return new KeyPair(privateKey, publicKey, type); - } -} diff --git a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs b/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs deleted file mode 100644 index 6bcfa30..0000000 --- a/OnixLabs.Security.Cryptography/KeyPair.Equatable.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Security.Cryptography; - -public sealed partial class KeyPair : IEquatable -{ - /// - /// Checks for equality between this instance and another object. - /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public bool Equals(KeyPair? other) - { - return ReferenceEquals(this, other) - || other is not null - && other.PrivateKey == PrivateKey - && other.PublicKey == PublicKey; - } - - /// - /// Checks for equality between this instance and another object. - /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public override bool Equals(object? obj) - { - return Equals(obj as KeyPair); - } - - /// - /// Serves as a hash code function for this instance. - /// - /// A hash code for this instance. - public override int GetHashCode() - { - return HashCode.Combine(PrivateKey, PublicKey); - } - - /// - /// Performs an equality check between two object instances. - /// - /// The left-hand instance to compare. - /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, . - public static bool operator ==(KeyPair left, KeyPair right) - { - return Equals(left, right); - } - - /// - /// Performs an inequality check between two object instances. - /// - /// The left-hand instance to compare. - /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, . - public static bool operator !=(KeyPair left, KeyPair right) - { - return !Equals(left, right); - } -} diff --git a/OnixLabs.Security.Cryptography/KeyPair.From.cs b/OnixLabs.Security.Cryptography/KeyPair.From.cs deleted file mode 100644 index c9e030e..0000000 --- a/OnixLabs.Security.Cryptography/KeyPair.From.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System; - -namespace OnixLabs.Security.Cryptography; - -public sealed partial class KeyPair -{ - /// - /// Creates a key pair from the specified public and private key components. - /// - /// The private key component of the key pair. - /// The public key component of the key pair. - /// The hash algorithm type of the key pair. - /// Returns a new instance from the key components. - /// If the private key hash algorithm type is mismatched. - /// If the public key hash algorithm type is mismatched. - /// If the private and public key components are mismatched. - public static KeyPair FromKeyComponents(PrivateKey privateKey, PublicKey publicKey, HashAlgorithmType type) - { - Require(privateKey.AlgorithmType == type, $"Private key hash algorithm type is mismatched with '{type}'.", nameof(privateKey)); - Require(publicKey.AlgorithmType == type, $"Public key hash algorithm type is mismatched with '{type}'.", nameof(publicKey)); - - byte[] random = Guid.NewGuid().ToByteArray(); - Hash hash = Hash.ComputeSha2Hash256(random); - DigitalSignature signature = privateKey.SignHash(hash); - - Check(signature.IsHashValid(hash, publicKey), "Invalid key pair. The specified public and private keys are mismatched."); - - return new KeyPair(privateKey, publicKey, type); - } -} diff --git a/OnixLabs.Security.Cryptography/KeyPair.cs b/OnixLabs.Security.Cryptography/KeyPair.cs deleted file mode 100644 index 19af1c4..0000000 --- a/OnixLabs.Security.Cryptography/KeyPair.cs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Security.Cryptography; - -/// -/// Represents a cryptographic public/private key pair. -/// -public sealed partial class KeyPair -{ - /// - /// Prevents new instances of the class from being created. - /// - /// The private key component of this key pair. - /// The public key component of this key pair. - /// The hash algorithm type of this key pair. - private KeyPair(PrivateKey privateKey, PublicKey publicKey, HashAlgorithmType algorithmType) - { - PrivateKey = privateKey; - PublicKey = publicKey; - AlgorithmType = algorithmType; - } - - /// - /// Gets the private key component of this key pair. - /// - public PrivateKey PrivateKey { get; } - - /// - /// Gets the public key component of this key pair. - /// - public PublicKey PublicKey { get; } - - /// - /// Gets the hash algorithm type of this key pair. - /// - public HashAlgorithmType AlgorithmType { get; } -} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Build.cs b/OnixLabs.Security.Cryptography/MerkleTree.Build.cs deleted file mode 100644 index c7f4e68..0000000 --- a/OnixLabs.Security.Cryptography/MerkleTree.Build.cs +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Collections.Generic; -using System.Linq; -using OnixLabs.Core.Linq; - -namespace OnixLabs.Security.Cryptography; - -public abstract partial class MerkleTree -{ - /// - /// Creates a from the specified leaves. - /// - /// The leaves from which to create a . - /// Returns a new computed from the specified leaves. - public static MerkleTree Create(params Hash[] leaves) - { - return Create(leaves.ToList()); - } - - /// - /// Creates a from the specified leaves. - /// - /// The leaves from which to create a . - /// Returns a new computed from the specified leaves. - public static MerkleTree Create(IEnumerable leaves) - { - IReadOnlyList nodes = leaves.Select(leaf => new MerkleTreeLeafNode(leaf)).ToList(); - - Require(nodes.IsNotEmpty(), - "Cannot construct a merkle tree from an empty list.", nameof(nodes)); - - Require(nodes.AllEqualBy(merkleTree => merkleTree.Hash.AlgorithmType), - "Cannot construct a merkle tree with different hash algorithm types.", nameof(nodes)); - - return Create(nodes); - } - - /// - /// Creates a from the specified leaves. - /// - /// The leaves from which to create a . - /// Returns a new computed from the specified leaves. - public static MerkleTree Create(params T[] leaves) where T : IHashable - { - return MerkleTree.Create(leaves); - } - - /// - /// Creates a from the specified leaves. - /// - /// The leaves from which to create a . - /// Returns a new computed from the specified leaves. - public static MerkleTree Create(IEnumerable leaves) where T : IHashable - { - return MerkleTree.Create(leaves); - } - - /// - /// Creates a from the specified leaves. - /// - /// The leaves from which to create a . - /// Returns a new computed from the specified leaves. - private static MerkleTree Create(IReadOnlyList nodes) - { - while (true) - { - if (nodes.IsSingle()) - { - return nodes.Single(); - } - - if (nodes.IsCountOdd()) - { - HashAlgorithmType type = nodes[0].Hash.AlgorithmType; - nodes = nodes.Append(new MerkleTreeEmptyNode(type)).ToList(); - } - - List mergedNodes = new(); - - for (int index = 0; index < nodes.Count; index += 2) - { - MerkleTree left = nodes[index]; - MerkleTree right = nodes[index + 1]; - mergedNodes.Add(new MerkleTreeBranchNode(left, right)); - } - - nodes = mergedNodes; - } - } -} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Create.cs b/OnixLabs.Security.Cryptography/MerkleTree.Create.cs new file mode 100644 index 0000000..9e339eb --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.Create.cs @@ -0,0 +1,73 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using OnixLabs.Core.Linq; + +namespace OnixLabs.Security.Cryptography; + +public abstract partial class MerkleTree +{ + /// + /// Creates a Merkle tree from the specified leaf nodes. + /// + /// The Merkle tree leaf nodes from which to build a Merkle tree. + /// The hash algorithm that will be used to hash together left-hand and right-hand nodes. + /// Returns a new node that represents the Merkle root. + public static MerkleTree Create(IEnumerable leaves, HashAlgorithm algorithm) + { + IReadOnlyList nodes = leaves.Select(leaf => new MerkleTreeLeafNode(leaf)).ToList(); + Require(nodes.IsNotEmpty(), "Cannot construct a Merkle tree from an empty list.", nameof(leaves)); + return BuildMerkleTree(nodes, algorithm); + } + + /// + /// Creates a Merkle tree from the specified leaf nodes. + /// + /// The Merkle tree leaf nodes from which to build a Merkle tree. + /// The hash algorithm that will be used to hash together left-hand and right-hand nodes. + /// Returns a new node that represents the Merkle root. + public static MerkleTree Create(IEnumerable leaves, HashAlgorithm algorithm) where T : IHashable + { + return MerkleTree.Create(leaves, algorithm); + } + + /// + /// Builds a Merkle tree from the specified nodes. + /// + /// The Merkle tree nodes from which to build a Merkle tree. + /// The hash algorithm that will be used to hash together left-hand and right-hand nodes. + /// Returns a new node that represents the Merkle root. + private static MerkleTree BuildMerkleTree(IReadOnlyList nodes, HashAlgorithm algorithm) + { + while (true) + { + if (nodes.IsSingle()) return nodes.Single(); + if (nodes.IsCountOdd()) nodes = nodes.Append(new MerkleTreeEmptyNode(algorithm)).ToArray(); + + List mergedNodes = []; + + for (int index = 0; index < nodes.Count; index += 2) + { + MerkleTree left = nodes[index]; + MerkleTree right = nodes[index + 1]; + mergedNodes.Add(new MerkleTreeBranchNode(left, right, algorithm)); + } + + nodes = mergedNodes.ToArray(); + } + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs b/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs index 50e63c4..8f94ce1 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,54 +16,56 @@ namespace OnixLabs.Security.Cryptography; -public abstract partial class MerkleTree : IEquatable +public abstract partial class MerkleTree { /// - /// Checks for equality between this instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public virtual bool Equals(MerkleTree? other) + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . + public bool Equals(MerkleTree? other) { - return ReferenceEquals(this, other) || other is not null && other.Hash == Hash; + return ReferenceEquals(this, other) + || other is not null + && other.Hash == Hash; } /// - /// Checks for equality between this instance and another object. + /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as MerkleTree); } /// - /// Serves as a hash code function for this instance. + /// Serves as a hash code function for the current instance. /// - /// A hash code for this instance. + /// Returns a hash code for the current instance. public override int GetHashCode() { return HashCode.Combine(GetType(), Hash); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(MerkleTree left, MerkleTree right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(MerkleTree left, MerkleTree right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs deleted file mode 100644 index 13dcff7..0000000 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Build.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Collections.Generic; -using System.Linq; -using OnixLabs.Core.Linq; - -namespace OnixLabs.Security.Cryptography; - -public abstract partial class MerkleTree -{ - /// - /// Creates a from the specified leaves. - /// - /// The leaves from which to create a . - /// Returns a new computed from the specified leaves. - public static MerkleTree Create(params T[] leaves) - { - return Create(leaves.ToList()); - } - - /// - /// Creates a from the specified leaves. - /// - /// The leaves from which to create a . - /// Returns a new computed from the specified leaves. - public static MerkleTree Create(IEnumerable leaves) - { - IReadOnlyList> nodes = leaves.Select(leaf => new MerkleTreeLeafNode(leaf)).ToList(); - - Require(nodes.IsNotEmpty(), - "Cannot construct a merkle tree from an empty list.", nameof(nodes)); - - Require(nodes.AllEqualBy(merkleTree => merkleTree.Hash.AlgorithmType), - "Cannot construct a merkle tree with different hash types.", nameof(nodes)); - - return Create(nodes); - } - - /// - /// Creates a from the specified leaves. - /// - /// The leaves from which to create a . - /// Returns a new computed from the specified leaves. - private static MerkleTree Create(IReadOnlyList> nodes) - { - while (true) - { - if (nodes.IsSingle()) - { - return nodes.Single(); - } - - if (nodes.IsCountOdd()) - { - HashAlgorithmType type = nodes[0].Hash.AlgorithmType; - nodes = nodes.Append(new MerkleTreeEmptyNode(type)).ToList(); - } - - List> mergedNodes = new(); - - for (int index = 0; index < nodes.Count; index += 2) - { - MerkleTree left = nodes[index]; - MerkleTree right = nodes[index + 1]; - mergedNodes.Add(new MerkleTreeBranchNode(left, right)); - } - - nodes = mergedNodes; - } - } -} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Create.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Create.cs new file mode 100644 index 0000000..d133d41 --- /dev/null +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Create.cs @@ -0,0 +1,62 @@ +// Copyright 2020 ONIXLabs +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using OnixLabs.Core.Linq; + +namespace OnixLabs.Security.Cryptography; + +public abstract partial class MerkleTree +{ + /// + /// Creates a Merkle tree from the specified leaf nodes. + /// + /// The Merkle tree leaf nodes from which to build a Merkle tree. + /// The hash algorithm that will be used to hash together left-hand and right-hand nodes. + /// Returns a new node that represents the Merkle root. + public static MerkleTree Create(IEnumerable leaves, HashAlgorithm algorithm) + { + IReadOnlyList> nodes = leaves.Select(leaf => new MerkleTreeLeafNode(leaf, algorithm)).ToList(); + Require(nodes.IsNotEmpty(), "Cannot construct a Merkle tree from an empty list.", nameof(leaves)); + return BuildMerkleTree(nodes, algorithm); + } + + /// + /// Builds a Merkle tree from the specified nodes. + /// + /// The Merkle tree nodes from which to build a Merkle tree. + /// The hash algorithm that will be used to hash together left-hand and right-hand nodes. + /// Returns a new node that represents the Merkle root. + private static MerkleTree BuildMerkleTree(IReadOnlyList> nodes, HashAlgorithm algorithm) + { + while (true) + { + if (nodes.IsSingle()) return nodes.Single(); + if (nodes.IsCountOdd()) nodes = nodes.Append(new MerkleTreeEmptyNode(algorithm)).ToList(); + + List> mergedNodes = []; + + for (int index = 0; index < nodes.Count; index += 2) + { + MerkleTree left = nodes[index]; + MerkleTree right = nodes[index + 1]; + mergedNodes.Add(new MerkleTreeBranchNode(left, right, algorithm)); + } + + nodes = mergedNodes; + } + } +} diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs index 12ca814..0ff59da 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,54 +16,56 @@ namespace OnixLabs.Security.Cryptography; -public abstract partial class MerkleTree : IEquatable> +public abstract partial class MerkleTree { /// - /// Checks for equality between this instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public virtual bool Equals(MerkleTree? other) + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . + public bool Equals(MerkleTree? other) { - return ReferenceEquals(this, other) || other is not null && other.Hash == Hash; + return ReferenceEquals(this, other) + || other is not null + && other.Hash == Hash; } /// - /// Checks for equality between this instance and another object. + /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as MerkleTree); } /// - /// Serves as a hash code function for this instance. + /// Serves as a hash code function for the current instance. /// - /// A hash code for this instance. + /// Returns a hash code for the current instance. public override int GetHashCode() { return HashCode.Combine(GetType(), Hash); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(MerkleTree left, MerkleTree right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(MerkleTree left, MerkleTree right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs index 8bff690..71c216c 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.Get.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,28 +14,29 @@ using System.Collections.Generic; using System.Collections.Immutable; +using System.Security.Cryptography; namespace OnixLabs.Security.Cryptography; public abstract partial class MerkleTree { /// - /// Obtains a hash-only, non-generic from the current . + /// Obtains a hash-only, non-generic instance from the current instance. /// - /// Returns a hash-only, non-generic from the current . - public MerkleTree ToMerkleTree() + /// Returns a new hash-only, non-generic instance from the current instance. + public MerkleTree ToMerkleTree(HashAlgorithm algorithm) { IEnumerable hashes = GetLeafHashes(); - return Create(hashes); + return Create(hashes, algorithm); } /// - /// Obtains the leaf values from the current . + /// Obtains the leaf values from the current instance. /// - /// Returns an containing the leaf values from the current . + /// Returns a new containing the leaf values from the current instance. public IReadOnlyList GetLeafValues() { - ICollection result = EmptyList(); + ICollection result = []; CollectLeafValues(this, result); return result.ToImmutableList(); } @@ -44,17 +45,17 @@ public IReadOnlyList GetLeafValues() /// Recursively iterates through the specified to collect leaf hashes. /// /// The current from which to begin iterating through. - /// The collection that will contain the leaf hashes from the current . - protected override void CollectLeafHashes(MerkleTree current, ICollection items) + /// The collection that will contain the leaf hashes from the current . + protected override void CollectLeafHashes(MerkleTree current, ICollection hashes) { switch (current) { - case MerkleTreeBranchNode branch: - CollectLeafHashes(branch.Left, items); - CollectLeafHashes(branch.Right, items); + case MerkleTreeBranchNode branch: + CollectLeafHashes(branch.Left, hashes); + CollectLeafHashes(branch.Right, hashes); break; - case MerkleTreeLeafNode leaf: - items.Add(leaf.Hash); + case MerkleTreeLeafNode leaf: + hashes.Add(leaf.Hash); break; } } @@ -63,17 +64,17 @@ protected override void CollectLeafHashes(MerkleTree current, ICollection /// Recursively iterates through the specified to collect leaf values. /// /// The current from which to begin iterating through. - /// The list that will contain the leaf values from the current . - private static void CollectLeafValues(MerkleTree current, ICollection items) + /// The list that will contain the leaf values from the current . + private static void CollectLeafValues(MerkleTree current, ICollection values) { switch (current) { - case MerkleTreeBranchNode branch: - CollectLeafValues(branch.Left, items); - CollectLeafValues(branch.Right, items); + case MerkleTreeBranchNode branch: + CollectLeafValues(branch.Left, values); + CollectLeafValues(branch.Right, values); break; - case MerkleTreeLeafNode leaf: - items.Add(leaf.Value); + case MerkleTreeLeafNode leaf: + values.Add(leaf.Value); break; } } diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs b/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs index 5b42d3b..3b9d788 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Generic.cs @@ -1,67 +1,74 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System.Security.Cryptography; +using OnixLabs.Core; + namespace OnixLabs.Security.Cryptography; /// /// Represents a generic Merkle tree. /// -public abstract partial class MerkleTree : MerkleTree where T : IHashable +public abstract partial class MerkleTree : MerkleTree, IValueEquatable> where T : IHashable { + /// + /// Initializes a new instance of the class. + /// This constructor is marked private to prevent external implementation. + /// + private MerkleTree(Hash hash) : base(hash) + { + } + /// /// Represents a generic Merkle tree branch node. /// - private sealed class MerkleTreeBranchNode : MerkleTree where THashable : IHashable + private sealed class MerkleTreeBranchNode : MerkleTree { /// - /// Creates a new instance of the class. + /// Creates a new instance of the class. /// /// The left-hand node. /// The right-hand node. - public MerkleTreeBranchNode(MerkleTree left, MerkleTree right) + /// The hash algorithm that will be used to hash together the left-hand and right-hand nodes. + public MerkleTreeBranchNode(MerkleTree left, MerkleTree right, HashAlgorithm algorithm) : base(Hash.Concatenate(algorithm, left.Hash, right.Hash)) { Left = left; Right = right; - Hash = Left.Hash.Concatenate(Right.Hash); } /// /// Gets the left-hand node. /// - public MerkleTree Left { get; } + public MerkleTree Left { get; } /// /// Gets the right-hand node. /// - public MerkleTree Right { get; } - - /// - /// Gets the of the current node. - /// - public override Hash Hash { get; } + public MerkleTree Right { get; } } /// /// Represents a generic Merkle tree leaf node. /// - private sealed class MerkleTreeLeafNode : MerkleTree where THashable : IHashable + private sealed class MerkleTreeLeafNode : MerkleTree { /// - /// Creates a new instance of the class. + /// Creates a new instance of the class. /// /// The underlying value of the current node. - public MerkleTreeLeafNode(THashable value) + /// The hash algorithm that will be used to hash the specified value. + public MerkleTreeLeafNode(T value, HashAlgorithm algorithm) : base(value.ComputeHash(algorithm)) { Value = value; } @@ -69,31 +76,20 @@ public MerkleTreeLeafNode(THashable value) /// /// Gets the underlying value of the current node. /// - public THashable Value { get; } - - /// - /// Gets the of the current node. - /// - public override Hash Hash => Value.ComputeHash(); + public T Value { get; } } /// /// Represents an empty generic Merkle tree node. /// - private sealed class MerkleTreeEmptyNode : MerkleTree where THashable : IHashable + private sealed class MerkleTreeEmptyNode : MerkleTree { /// - /// Creates a new instance of the class. + /// Creates a new instance of the class. /// - /// The for the current node. - public MerkleTreeEmptyNode(HashAlgorithmType type) + /// The hash algorithm that will be used to determine the size of the required empty hash. + public MerkleTreeEmptyNode(HashAlgorithm algorithm) : base(new Hash(0x00, algorithm.HashSize / 8)) { - Hash = Hash.CreateAllZeroHash(type); } - - /// - /// Gets the of the current node. - /// - public override Hash Hash { get; } } } diff --git a/OnixLabs.Security.Cryptography/MerkleTree.Get.cs b/OnixLabs.Security.Cryptography/MerkleTree.Get.cs index fd1b661..17a3e72 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.Get.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.Get.cs @@ -1,17 +1,18 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -20,12 +21,12 @@ namespace OnixLabs.Security.Cryptography; public abstract partial class MerkleTree { /// - /// Obtains the leaf hashes from the current . + /// Obtains the leaf hashes from the current instance. /// - /// Returns an containing the leaf hashes from the current . + /// Returns a new instance containing the leaf hashes from the current instance. public IReadOnlyList GetLeafHashes() { - ICollection result = EmptyList(); + ICollection result = []; CollectLeafHashes(this, result); return result.ToImmutableList(); } @@ -34,17 +35,17 @@ public IReadOnlyList GetLeafHashes() /// Recursively iterates through the specified to collect leaf hashes. /// /// The current from which to begin iterating through. - /// The list that will contain the leaf hashes from the current . - protected virtual void CollectLeafHashes(MerkleTree current, ICollection items) + /// The collection that will contain the leaf hashes from the current . + protected virtual void CollectLeafHashes(MerkleTree current, ICollection hashes) { switch (current) { case MerkleTreeBranchNode branch: - CollectLeafHashes(branch.Left, items); - CollectLeafHashes(branch.Right, items); + CollectLeafHashes(branch.Left, hashes); + CollectLeafHashes(branch.Right, hashes); break; case MerkleTreeLeafNode leaf: - items.Add(leaf.Hash); + hashes.Add(leaf.Hash); break; } } diff --git a/OnixLabs.Security.Cryptography/MerkleTree.To.cs b/OnixLabs.Security.Cryptography/MerkleTree.To.cs index 88468c9..355bc24 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.To.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.To.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -16,11 +16,20 @@ namespace OnixLabs.Security.Cryptography; public abstract partial class MerkleTree { + /// + /// Gets the underlying representation of the current instance. + /// + /// Return the underlying representation of the current instance. + public byte[] ToByteArray() + { + return Hash.ToByteArray(); + } + /// /// Returns a that represents the current object. /// - /// A that represents the current object. - public sealed override string ToString() + /// Returns that represents the current object. + public override string ToString() { return Hash.ToString(); } diff --git a/OnixLabs.Security.Cryptography/MerkleTree.cs b/OnixLabs.Security.Cryptography/MerkleTree.cs index 0fa9540..cf6fab2 100644 --- a/OnixLabs.Security.Cryptography/MerkleTree.cs +++ b/OnixLabs.Security.Cryptography/MerkleTree.cs @@ -1,35 +1,39 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System.Security.Cryptography; + namespace OnixLabs.Security.Cryptography; /// /// Represents a Merkle tree. /// -public abstract partial class MerkleTree +public abstract partial class MerkleTree : ICryptoPrimitive { /// - /// Prevents an instance of from being created. + /// Initializes a new instance of the class. + /// This constructor is marked internal to prevent external implementation. /// - internal MerkleTree() + internal MerkleTree(Hash hash) { + Hash = hash; } /// /// Gets the of the current node. /// - public abstract Hash Hash { get; } + public Hash Hash { get; } /// /// Represents a Merkle tree branch node. @@ -41,11 +45,11 @@ private sealed class MerkleTreeBranchNode : MerkleTree /// /// The left-hand node. /// The right-hand node. - public MerkleTreeBranchNode(MerkleTree left, MerkleTree right) + /// The hash algorithm that will be used to hash together the left-hand and right-hand nodes. + public MerkleTreeBranchNode(MerkleTree left, MerkleTree right, HashAlgorithm algorithm) : base(Hash.Concatenate(algorithm, left.Hash, right.Hash)) { Left = left; Right = right; - Hash = Left.Hash.Concatenate(Right.Hash); } /// @@ -57,11 +61,6 @@ public MerkleTreeBranchNode(MerkleTree left, MerkleTree right) /// Gets the right-hand node. /// public MerkleTree Right { get; } - - /// - /// Gets the of the current node. - /// - public override Hash Hash { get; } } /// @@ -73,15 +72,9 @@ private sealed class MerkleTreeLeafNode : MerkleTree /// Creates a new instance of the class. /// /// The value for the current node. - public MerkleTreeLeafNode(Hash hash) + public MerkleTreeLeafNode(Hash hash) : base(hash) { - Hash = hash; } - - /// - /// Gets the of the current node. - /// - public override Hash Hash { get; } } /// @@ -92,15 +85,9 @@ private sealed class MerkleTreeEmptyNode : MerkleTree /// /// Creates a new instance of the class. /// - /// The for the current node. - public MerkleTreeEmptyNode(HashAlgorithmType type) + /// The hash algorithm that will be used to determine the size of the required empty hash. + public MerkleTreeEmptyNode(HashAlgorithm algorithm) : base(new Hash(0x00, algorithm.HashSize / 8)) { - Hash = Hash.CreateAllZeroHash(type); } - - /// - /// Gets the of the current node. - /// - public override Hash Hash { get; } } } diff --git a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj index ace5d43..af112b2 100644 --- a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj +++ b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj @@ -8,7 +8,7 @@ en enable true - Copyright © ONIXLabs 2020-2023 + Copyright © ONIXLabs 2020 https://github.com/onix-labs/onixlabs-dotnet 6.0.0 12 @@ -44,6 +44,5 @@ - diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs b/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs index 37369a6..ae5332f 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,58 +18,57 @@ namespace OnixLabs.Security.Cryptography; -public abstract partial class PrivateKey : IEquatable +public abstract partial class PrivateKey { /// - /// Checks for equality between this instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public virtual bool Equals(PrivateKey? other) + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . + public bool Equals(PrivateKey? other) { return ReferenceEquals(this, other) || other is not null && other.GetType() == GetType() - && other.KeyData.SequenceEqual(KeyData) - && other.AlgorithmType == AlgorithmType; + && other.KeyData.SequenceEqual(KeyData); } /// - /// Checks for equality between this instance and another object. + /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as PrivateKey); } /// - /// Serves as a hash code function for this instance. + /// Serves as a hash code function for the current instance. /// - /// A hash code for this instance. + /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(GetType(), AlgorithmType, KeyData.GetContentHashCode()); + return HashCode.Combine(GetType(), KeyData.GetContentHashCode()); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(PrivateKey left, PrivateKey right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(PrivateKey left, PrivateKey right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Export.cs b/OnixLabs.Security.Cryptography/PrivateKey.Export.cs index 0721de3..8757e64 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Export.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,40 +20,16 @@ namespace OnixLabs.Security.Cryptography; public abstract partial class PrivateKey { /// - /// Exports the key in PKCS #8 format. + /// Exports the cryptographic private key data in PKCS #8 format. /// - /// Returns the key in PKCS #8 format. - public abstract byte[] ExportPkcs8Key(); + /// Returns a new instance containing the cryptographic private key data in PKCS #8 format. + public abstract byte[] ExportPkcs8PrivateKey(); /// - /// Exports the key in encrypted PKCS #8 format. + /// Exports the cryptographic private key data in encrypted PKCS #8 format. /// /// The password to use for encryption. /// The parameters required for password based encryption. - /// Returns the key in encrypted PKCS #8 format. - public abstract byte[] ExportPkcs8Key(ReadOnlySpan password, PbeParameters parameters); - - /// - /// Exports the key in encrypted PKCS #8 format. - /// - /// The password to use for encryption. - /// The parameters required for password based encryption. - /// Returns the key in encrypted PKCS #8 format. - public byte[] ExportPkcs8Key(char[] password, PbeParameters parameters) - { - ReadOnlySpan characters = password.AsSpan(); - return ExportPkcs8Key(characters, parameters); - } - - /// - /// Exports the key in encrypted PKCS #8 format. - /// - /// The password to use for encryption. - /// The parameters required for password based encryption. - /// Returns the key in encrypted PKCS #8 format. - public byte[] ExportPkcs8Key(string password, PbeParameters parameters) - { - char[] characters = password.ToCharArray(); - return ExportPkcs8Key(characters, parameters); - } + /// Returns a new instance containing the cryptographic private key data in PKCS #8 format. + public abstract byte[] ExportPkcs8PrivateKey(ReadOnlySpan password, PbeParameters parameters); } diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Get.cs b/OnixLabs.Security.Cryptography/PrivateKey.Get.cs index 9fb0252..c264d2e 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.Get.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,8 +17,8 @@ namespace OnixLabs.Security.Cryptography; public abstract partial class PrivateKey { /// - /// Gets the public key component from this private key. + /// Gets the cryptographic public key component from the current cryptographic private key. /// - /// Returns the public key component from this private key. + /// Returns a new instance containing the cryptographic public key component from the current cryptographic private key. public abstract PublicKey GetPublicKey(); } diff --git a/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs deleted file mode 100644 index 3982149..0000000 --- a/OnixLabs.Security.Cryptography/PrivateKey.Sign.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -namespace OnixLabs.Security.Cryptography; - -public abstract partial class PrivateKey -{ - /// - /// Computes a from the specified unsigned data. - /// - /// The unsigned data from which to compute a . - /// Returns a from the specified unsigned data. - public abstract DigitalSignature SignData(byte[] unsignedData); - - /// - /// Computes a from the specified unsigned hash. - /// - /// The unsigned hash from which to compute a . - /// Returns a from the specified unsigned hash. - public abstract DigitalSignature SignHash(byte[] unsignedHash); - - /// - /// Computes a from the specified unsigned hash. - /// - /// The unsigned hash from which to compute a . - /// Returns a from the specified unsigned hash. - public DigitalSignature SignHash(Hash unsignedHash) - { - byte[] unsignedHashBytes = unsignedHash.ToByteArray(); - return SignHash(unsignedHashBytes); - } -} diff --git a/OnixLabs.Security.Cryptography/PrivateKey.To.cs b/OnixLabs.Security.Cryptography/PrivateKey.To.cs index 42ac696..1f24ed1 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.To.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.To.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,61 +14,24 @@ using System; using OnixLabs.Core; -using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; public abstract partial class PrivateKey { /// - /// Returns a array that represents the underlying private key data. + /// Gets the underlying representation of the current instance. /// - /// Returns a array that represents the underlying private key data. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { return KeyData.Copy(); } /// - /// Returns a value that represents the underlying private key data. + /// Returns a that represents the current object. /// - /// Returns a value that represents the underlying private key data. - public Base16 ToBase16() - { - return Base16.Create(KeyData); - } - - /// - /// Returns a value that represents the underlying private key data. - /// - /// Returns a value that represents the underlying private key data. - public Base32 ToBase32() - { - return Base32.Create(KeyData); - } - - /// - /// Returns a value that represents the underlying private key data. - /// - /// Returns a value that represents the underlying private key data. - public Base58 ToBase58() - { - return Base58.Create(KeyData); - } - - /// - /// Returns a value that represents the underlying private key data. - /// - /// Returns a value that represents the underlying private key data. - public Base64 ToBase64() - { - return Base64.Create(KeyData); - } - - /// - /// Returns a that represents the current object. - /// - /// A that represents the current object. + /// Returns that represents the current object. public override string ToString() { return Convert.ToHexString(KeyData).ToLower(); diff --git a/OnixLabs.Security.Cryptography/PrivateKey.cs b/OnixLabs.Security.Cryptography/PrivateKey.cs index 1cc3573..4b9fa09 100644 --- a/OnixLabs.Security.Cryptography/PrivateKey.cs +++ b/OnixLabs.Security.Cryptography/PrivateKey.cs @@ -1,45 +1,29 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core; +using System; namespace OnixLabs.Security.Cryptography; /// -/// Represents the base class for private key implementations. +/// Represents a cryptographic private key. /// -public abstract partial class PrivateKey +/// The underlying key data of the cryptographic private key. +public abstract partial class PrivateKey(ReadOnlySpan keyData) : ICryptoPrimitive { /// - /// Initializes a new instance of the class. + /// Gets the cryptographic private key data. /// - /// The private key data. - /// The hash algorithm type for computing signature data. - protected PrivateKey(byte[] data, HashAlgorithmType type) - { - type.GetHashAlgorithmName(); - KeyData = data.Copy(); - AlgorithmType = type; - } - - /// - /// Gets the underlying private key data. - /// - protected byte[] KeyData { get; } - - /// - /// Gets the hash algorithm type for computing signature data. - /// - public HashAlgorithmType AlgorithmType { get; } + protected byte[] KeyData { get; } = keyData.ToArray(); } diff --git a/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs b/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs index 01e1599..5a6a110 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,58 +18,57 @@ namespace OnixLabs.Security.Cryptography; -public abstract partial class PublicKey : IEquatable +public abstract partial class PublicKey { /// - /// Checks for equality between this instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public virtual bool Equals(PublicKey? other) + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . + public bool Equals(PublicKey? other) { return ReferenceEquals(this, other) || other is not null && other.GetType() == GetType() - && other.KeyData.SequenceEqual(KeyData) - && other.AlgorithmType == AlgorithmType; + && other.KeyData.SequenceEqual(KeyData); } /// - /// Checks for equality between this instance and another object. + /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return Equals(obj as PublicKey); } /// - /// Serves as a hash code function for this instance. + /// Serves as a hash code function for the current instance. /// - /// A hash code for this instance. + /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(GetType(), AlgorithmType, KeyData.GetContentHashCode()); + return HashCode.Combine(GetType(), KeyData.GetContentHashCode()); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are equal; otherwise, . + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(PublicKey left, PublicKey right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// /// The left-hand instance to compare. /// The right-hand instance to compare. - /// True if the instances are not equal; otherwise, . + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(PublicKey left, PublicKey right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/PublicKey.To.cs b/OnixLabs.Security.Cryptography/PublicKey.To.cs index fb3bf45..615fc5b 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.To.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.To.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,61 +14,24 @@ using System; using OnixLabs.Core; -using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; public abstract partial class PublicKey { /// - /// Returns a array that represents the underlying public key data. + /// Gets the underlying representation of the current instance. /// - /// Returns a array that represents the underlying public key data. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { return KeyData.Copy(); } /// - /// Returns a value that represents the underlying public key data. + /// Returns a that represents the current object. /// - /// Returns a value that represents the underlying public key data. - public Base16 ToBase16() - { - return Base16.Create(KeyData); - } - - /// - /// Returns a value that represents the underlying public key data. - /// - /// Returns a value that represents the underlying public key data. - public Base32 ToBase32() - { - return Base32.Create(KeyData); - } - - /// - /// Returns a value that represents the underlying public key data. - /// - /// Returns a value that represents the underlying public key data. - public Base58 ToBase58() - { - return Base58.Create(KeyData); - } - - /// - /// Returns a value that represents the underlying public key data. - /// - /// Returns a value that represents the underlying public key data. - public Base64 ToBase64() - { - return Base64.Create(KeyData); - } - - /// - /// Returns a that represents the current object. - /// - /// A that represents the current object. + /// Returns that represents the current object. public override string ToString() { return Convert.ToHexString(KeyData).ToLower(); diff --git a/OnixLabs.Security.Cryptography/PublicKey.Verify.cs b/OnixLabs.Security.Cryptography/PublicKey.Verify.cs deleted file mode 100644 index d1dee72..0000000 --- a/OnixLabs.Security.Cryptography/PublicKey.Verify.cs +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Security.Cryptography; - -namespace OnixLabs.Security.Cryptography; - -public abstract partial class PublicKey -{ - /// - /// Determines whether the specified was signed by the private component of this public key. - /// - /// The to validate. - /// The unsigned data to validate. - /// Returns if the specified was signed by the private component of this public key; otherwise, . - public abstract bool IsDataValid(DigitalSignature signature, byte[] unsignedData); - - /// - /// Determines whether the specified was signed by the private component of this public key. - /// - /// The to validate. - /// The unsigned hash to validate. - /// Returns if the specified was signed by the private component of this public key; otherwise, . - public abstract bool IsHashValid(DigitalSignature signature, byte[] unsignedHash); - - /// - /// Determines whether the specified was signed by the private component of this public key. - /// - /// The to validate. - /// The unsigned hash to validate. - /// Returns if the specified was signed by the private component of this public key; otherwise, . - public bool IsHashValid(DigitalSignature signature, Hash unsignedHash) - { - byte[] unsignedHashBytes = unsignedHash.ToByteArray(); - return IsHashValid(signature, unsignedHashBytes); - } - - /// - /// Verifies whether the specified was signed by the private component of this public key. - /// - /// The to verify. - /// he unsigned data to verify. - /// If the specified was not signed by the private component of this public key. - public void VerifyData(DigitalSignature signature, byte[] unsignedData) - { - if (!IsDataValid(signature, unsignedData)) - { - throw new CryptographicException("The specified digital signature was not signed with this key."); - } - } - - /// - /// Verifies whether the specified was signed by the private component of this public key. - /// - /// The to verify. - /// he unsigned hash to verify. - /// If the specified was not signed by the private component of this public key. - public void VerifyHash(DigitalSignature signature, byte[] unsignedHash) - { - if (!IsHashValid(signature, unsignedHash)) - { - throw new CryptographicException("The specified digital signature was not signed with this key."); - } - } - - /// - /// Verifies whether the specified was signed by the private component of this public key. - /// - /// The to verify. - /// he unsigned hash to verify. - /// If the specified was not signed by the private component of this public key. - public void VerifyHash(DigitalSignature signature, Hash unsignedHash) - { - byte[] unsignedHashBytes = unsignedHash.ToByteArray(); - VerifyHash(signature, unsignedHashBytes); - } -} diff --git a/OnixLabs.Security.Cryptography/PublicKey.cs b/OnixLabs.Security.Cryptography/PublicKey.cs index 9a6ed24..a1bbd71 100644 --- a/OnixLabs.Security.Cryptography/PublicKey.cs +++ b/OnixLabs.Security.Cryptography/PublicKey.cs @@ -1,45 +1,29 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core; +using System; namespace OnixLabs.Security.Cryptography; /// -/// Represents the base class for public key implementations. +/// Represents a cryptographic public key. /// -public abstract partial class PublicKey +/// The underlying key data of the cryptographic public key. +public abstract partial class PublicKey(ReadOnlySpan keyData) : ICryptoPrimitive { /// - /// Creates a new instance of the class. + /// Gets the cryptographic public key data. /// - /// The public key data. - /// The hash algorithm type for computing signature data. - protected PublicKey(byte[] data, HashAlgorithmType type) - { - type.GetHashAlgorithmName(); - KeyData = data.Copy(); - AlgorithmType = type; - } - - /// - /// Gets the underlying public key data. - /// - protected byte[] KeyData { get; } - - /// - /// Gets the hash algorithm type for computing signature data. - /// - public HashAlgorithmType AlgorithmType { get; } + protected byte[] KeyData { get; } = keyData.ToArray(); } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs index 2a27fe3..ac6062c 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Create.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -13,73 +13,31 @@ // limitations under the License. using System.Security.Cryptography; -using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; public sealed partial class RsaPrivateKey { /// - /// Creates an from the specified key data and hash algorithm type. + /// Creates a new RSA cryptographic private key. /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey Create(byte[] key, HashAlgorithmType type, RSASignaturePadding padding) + /// Returns a new instance. + public static RsaPrivateKey Create() { - return new RsaPrivateKey(key, type, padding); + using RSA key = RSA.Create(); + byte[] keyData = key.ExportRSAPrivateKey(); + return new RsaPrivateKey(keyData); } /// - /// Creates an from the specified value. + /// Creates a new RSA cryptographic private key. /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey Create(Base16 key, HashAlgorithmType type, RSASignaturePadding padding) + /// The RSA parameters from which to create a new RSA cryptographic private key. + /// Returns a new instance. + public static RsaPrivateKey Create(RSAParameters parameters) { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type, padding); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey Create(Base32 key, HashAlgorithmType type, RSASignaturePadding padding) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type, padding); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey Create(Base58 key, HashAlgorithmType type, RSASignaturePadding padding) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type, padding); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPrivateKey Create(Base64 key, HashAlgorithmType type, RSASignaturePadding padding) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type, padding); + using RSA key = RSA.Create(parameters); + byte[] keyData = key.ExportRSAPrivateKey(); + return new RsaPrivateKey(keyData); } } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs index a47cdcc..2b16587 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Export.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,26 +20,24 @@ namespace OnixLabs.Security.Cryptography; public sealed partial class RsaPrivateKey { /// - /// Exports the key in PKCS #8 format. + /// Exports the RSA cryptographic private key data in PKCS #8 format. /// - /// Returns the key in PKCS #8 format. - public override byte[] ExportPkcs8Key() + /// Returns a new instance containing the RSA cryptographic private key data in PKCS #8 format. + public override byte[] ExportPkcs8PrivateKey() { - using RSA privateKey = RSA.Create(); - privateKey.ImportRSAPrivateKey(KeyData, out int _); - return privateKey.ExportPkcs8PrivateKey(); + using RSA key = ImportKeyData(); + return key.ExportPkcs8PrivateKey(); } /// - /// Exports the key in encrypted PKCS #8 format. + /// Exports the RSA cryptographic private key data in encrypted PKCS #8 format. /// /// The password to use for encryption. /// The parameters required for password based encryption. - /// Returns the key in encrypted PKCS #8 format. - public override byte[] ExportPkcs8Key(ReadOnlySpan password, PbeParameters parameters) + /// Returns a new instance containing the RSA cryptographic private key data in PKCS #8 format. + public override byte[] ExportPkcs8PrivateKey(ReadOnlySpan password, PbeParameters parameters) { - using RSA privateKey = RSA.Create(); - privateKey.ImportRSAPrivateKey(KeyData, out int _); - return privateKey.ExportEncryptedPkcs8PrivateKey(password, parameters); + using RSA key = ImportKeyData(); + return key.ExportEncryptedPkcs8PrivateKey(password, parameters); } } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs index 546f72b..1c86fbf 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Get.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,16 +19,13 @@ namespace OnixLabs.Security.Cryptography; public sealed partial class RsaPrivateKey { /// - /// Gets the public key component from this private key. + /// Gets the RSA cryptographic public key component from the current RSA cryptographic private key. /// - /// Returns the public key component from this private key. - public override PublicKey GetPublicKey() + /// Returns a new instance containing the RSA cryptographic public key component from the current RSA cryptographic private key. + public override RsaPublicKey GetPublicKey() { - using RSA privateKey = RSA.Create(); - - privateKey.ImportRSAPrivateKey(KeyData, out int _); - byte[] publicKey = privateKey.ExportRSAPublicKey(); - - return new RsaPublicKey(publicKey, AlgorithmType, Padding); + using RSA key = ImportKeyData(); + byte[] keyData = key.ExportRSAPublicKey(); + return new RsaPublicKey(keyData); } } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs index 2fb8511..5c07ad3 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Import.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,144 +20,63 @@ namespace OnixLabs.Security.Cryptography; public sealed partial class RsaPrivateKey { /// - /// Imports a PKCS #8 formatted key. + /// Imports the RSA cryptographic private key data in PKCS #8 format. /// - /// The key data to import. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static RsaPrivateKey ImportPkcs8Key(ReadOnlySpan data, HashAlgorithmType type, RSASignaturePadding padding) + /// The cryptographic private key data to import. + /// Returns a new instance from the imported cryptographic private key data. + public static RsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data) { - RSA privateKey = RSA.Create(); - - privateKey.ImportPkcs8PrivateKey(data, out int _); - byte[] bytes = privateKey.ExportRSAPrivateKey(); - - return Create(bytes, type, padding); - } - - /// - /// Imports a PKCS #8 formatted key. - /// - /// The key data to import. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static RsaPrivateKey ImportPkcs8Key(byte[] data, HashAlgorithmType type, RSASignaturePadding padding) - { - ReadOnlySpan bytes = data.AsSpan(); - return ImportPkcs8Key(bytes, type, padding); - } - - /// - /// Imports an encrypted PKCS #8 formatted key. - /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static RsaPrivateKey ImportPkcs8Key( - ReadOnlySpan data, - ReadOnlySpan password, - HashAlgorithmType type, - RSASignaturePadding padding) - { - RSA privateKey = RSA.Create(); - - privateKey.ImportEncryptedPkcs8PrivateKey(password, data, out int _); - byte[] bytes = privateKey.ExportRSAPrivateKey(); - - return Create(bytes, type, padding); - } - - /// - /// Imports an encrypted PKCS #8 formatted key. - /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static RsaPrivateKey ImportPkcs8Key( - ReadOnlySpan data, - char[] password, - HashAlgorithmType type, - RSASignaturePadding padding) - { - ReadOnlySpan characters = password.AsSpan(); - return ImportPkcs8Key(data, characters, type, padding); + return ImportPkcs8PrivateKey(data, out int _); } /// - /// Imports an encrypted PKCS #8 formatted key. + /// Imports the RSA cryptographic private key data in PKCS #8 format. /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static RsaPrivateKey ImportPkcs8Key( - ReadOnlySpan data, - string password, - HashAlgorithmType type, - RSASignaturePadding padding) + /// The cryptographic private key data to import. + /// The number of bytes read from the input data. + /// Returns a new instance from the imported cryptographic private key data. + public static RsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, out int bytesRead) { - ReadOnlySpan characters = password.AsSpan(); - return ImportPkcs8Key(data, characters, type, padding); + using RSA key = RSA.Create(); + key.ImportPkcs8PrivateKey(data, out bytesRead); + byte[] keyData = key.ExportRSAPrivateKey(); + return new RsaPrivateKey(keyData); } /// - /// Imports an encrypted PKCS #8 formatted key. + /// Imports the RSA cryptographic private key data in encrypted PKCS #8 format. /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static RsaPrivateKey ImportPkcs8Key( - byte[] data, - ReadOnlySpan password, - HashAlgorithmType type, - RSASignaturePadding padding) + /// The cryptographic private key data to import. + /// The password required for password based decryption. + /// Returns a new instance from the imported cryptographic private key data. + public static RsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, ReadOnlySpan password) { - ReadOnlySpan bytes = data.AsSpan(); - return ImportPkcs8Key(bytes, password, type, padding); + return ImportPkcs8PrivateKey(data, password, out int _); } /// - /// Imports an encrypted PKCS #8 formatted key. + /// Imports the RSA cryptographic private key data in encrypted PKCS #8 format. /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static RsaPrivateKey ImportPkcs8Key( - byte[] data, - char[] password, - HashAlgorithmType type, - RSASignaturePadding padding) + /// The cryptographic private key data to import. + /// The password required for password based decryption. + /// The number of bytes read from the input data. + /// Returns a new instance from the imported cryptographic private key data. + public static RsaPrivateKey ImportPkcs8PrivateKey(ReadOnlySpan data, ReadOnlySpan password, out int bytesRead) { - ReadOnlySpan bytes = data.AsSpan(); - return ImportPkcs8Key(bytes, password, type, padding); + using RSA key = RSA.Create(); + key.ImportEncryptedPkcs8PrivateKey(password, data, out bytesRead); + byte[] keyData = key.ExportRSAPrivateKey(); + return new RsaPrivateKey(keyData); } /// - /// Imports an encrypted PKCS #8 formatted key. + /// Imports the key data into a new instance. /// - /// The key data to import. - /// The password to decrypt the key data. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified PKCS #8 key data. - public static RsaPrivateKey ImportPkcs8Key( - byte[] data, - string password, - HashAlgorithmType type, - RSASignaturePadding padding) + /// Returns a new instance containing the imported key data. + private RSA ImportKeyData() { - ReadOnlySpan bytes = data.AsSpan(); - return ImportPkcs8Key(bytes, password, type, padding); + RSA algorithm = RSA.Create(); + algorithm.ImportRSAPrivateKey(KeyData, out int _); + return algorithm; } } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs index b54c0c7..f1908fb 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.Sign.cs @@ -1,52 +1,103 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.IO; using System.Security.Cryptography; +using OnixLabs.Core; namespace OnixLabs.Security.Cryptography; public sealed partial class RsaPrivateKey { /// - /// Computes a from the specified unsigned data. + /// Hashes the specified data and signs the resulting hash. /// - /// The unsigned data from which to compute a . - /// Returns a from the specified unsigned data. - public override DigitalSignature SignData(byte[] unsignedData) + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding) { - using RSA privateKey = RSA.Create(); + using RSA key = ImportKeyData(); + return key.SignData(data, algorithm, padding); + } - privateKey.ImportRSAPrivateKey(KeyData, out int _); - HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - byte[] signedData = privateKey.SignData(unsignedData, name, Padding); + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that will be used to hash the input data. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.SignData(data.Slice(offset, count), algorithm, padding); + } - return DigitalSignature.Create(signedData); + /// + /// Hashes the specified data and signs the resulting hash. + /// + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.SignData(data, algorithm, padding); } /// - /// Computes a from the specified unsigned hash. + /// Hashes the specified data and signs the resulting hash. /// - /// The unsigned hash from which to compute a . - /// Returns a from the specified unsigned hash. - public override DigitalSignature SignHash(byte[] unsignedHash) + /// The input data to hash and sign. + /// The hash algorithm that will be used to hash the input data. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignData(IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding) { - using RSA privateKey = RSA.Create(); + using RSA key = ImportKeyData(); + return key.SignData(data.ToByteArray(), algorithm, padding); + } - privateKey.ImportRSAPrivateKey(KeyData, out int _); - HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - byte[] signedData = privateKey.SignHash(unsignedHash, name, Padding); + /// + /// Signs the specified . + /// + /// The hash to sign. + /// The hash algorithm that will be used to hash the input hash. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignHash(Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.SignHash(hash.ToByteArray(), algorithm, padding); + } - return DigitalSignature.Create(signedData); + /// + /// Signs the specified . + /// + /// The hash to sign. + /// The hash algorithm that will be used to hash the input hash. + /// The RSA signature padding mode that will be used to generate the cryptographic digital signature. + /// Returns a new instance containing the cryptographic digital signature. + public byte[] SignHash(ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.SignHash(hash, algorithm, padding); } } diff --git a/OnixLabs.Security.Cryptography/RsaPrivateKey.cs b/OnixLabs.Security.Cryptography/RsaPrivateKey.cs index 8e12f38..c5c462f 100644 --- a/OnixLabs.Security.Cryptography/RsaPrivateKey.cs +++ b/OnixLabs.Security.Cryptography/RsaPrivateKey.cs @@ -1,39 +1,23 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using System.Security.Cryptography; +using System; namespace OnixLabs.Security.Cryptography; /// -/// Represents an RSA private key. +/// Represents an RSA cryptographic private key. /// -public sealed partial class RsaPrivateKey : PrivateKey -{ - /// - /// Creates a new instance of the class. - /// - /// The private key data. - /// The hash algorithm type for computing signature data. - /// The for computing signature data. - internal RsaPrivateKey(byte[] data, HashAlgorithmType type, RSASignaturePadding padding) : base(data, type) - { - Padding = padding; - } - - /// - /// Gets the for computing signature data. - /// - public RSASignaturePadding Padding { get; } -} +/// The underlying key data of the RSA cryptographic private key. +public sealed partial class RsaPrivateKey(ReadOnlySpan keyData) : PrivateKey(keyData), IRsaPrivateKey; diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs deleted file mode 100644 index 93acd1e..0000000 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Create.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright © 2020 ONIXLabs -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -using System.Security.Cryptography; -using OnixLabs.Core.Text; - -namespace OnixLabs.Security.Cryptography; - -public sealed partial class RsaPublicKey -{ - /// - /// Creates an from the specified key data and hash algorithm type. - /// - /// The key data from which to construct a public key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey Create(byte[] key, HashAlgorithmType type, RSASignaturePadding padding) - { - return new RsaPublicKey(key, type, padding); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey Create(Base16 key, HashAlgorithmType type, RSASignaturePadding padding) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type, padding); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey Create(Base32 key, HashAlgorithmType type, RSASignaturePadding padding) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type, padding); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey Create(Base58 key, HashAlgorithmType type, RSASignaturePadding padding) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type, padding); - } - - /// - /// Creates an from the specified value. - /// - /// The key data from which to construct a private key. - /// The for computing signature data. - /// The for computing signature data. - /// Returns an from the specified key data and hash algorithm type. - public static RsaPublicKey Create(Base64 key, HashAlgorithmType type, RSASignaturePadding padding) - { - byte[] bytes = key.ToByteArray(); - return Create(bytes, type, padding); - } -} diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Import.cs similarity index 61% rename from OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs rename to OnixLabs.Security.Cryptography/RsaPublicKey.Import.cs index d3bd821..827a138 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Equatable.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Import.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,17 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.Security.Cryptography; + namespace OnixLabs.Security.Cryptography; public sealed partial class RsaPublicKey { /// - /// Checks for equality between this instance and another object. + /// Imports the key data into a new instance. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . - public override bool Equals(PublicKey? other) + /// Returns a new instance containing the imported key data. + private RSA ImportKeyData() { - return base.Equals(other) && other is RsaPublicKey rsaOther && rsaOther.Padding == Padding; + RSA algorithm = RSA.Create(); + algorithm.ImportRSAPublicKey(KeyData, out int _); + return algorithm; } } diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs index c2895b8..c383d76 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.Verify.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,39 +12,419 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.IO; using System.Security.Cryptography; +using OnixLabs.Core; namespace OnixLabs.Security.Cryptography; public sealed partial class RsaPublicKey { /// - /// Determines whether the specified was signed by the private component of this public key. + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. /// - /// The to validate. - /// The unsigned data to validate. - /// Returns if the specified was signed by the private component of this public key; otherwise, . - public override bool IsDataValid(DigitalSignature signature, byte[] unsignedData) + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding) { - using RSA publicKey = RSA.Create(); - publicKey.ImportRSAPublicKey(KeyData, out int _); - byte[] signatureData = signature.ToByteArray(); - HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - return publicKey.VerifyData(unsignedData, signatureData, name, Padding); + using RSA key = ImportKeyData(); + return key.VerifyData(data, signature, algorithm, padding); } /// - /// Determines whether the specified was signed by the private component of this public key. + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. /// - /// The to validate. - /// The unsigned hash to validate. - /// Returns if the specified was signed by the private component of this public key; otherwise, . - public override bool IsHashValid(DigitalSignature signature, byte[] unsignedHash) + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding) { - using RSA publicKey = RSA.Create(); - publicKey.ImportRSAPublicKey(KeyData, out int _); - byte[] signatureData = signature.ToByteArray(); - HashAlgorithmName name = AlgorithmType.GetHashAlgorithmName(); - return publicKey.VerifyHash(unsignedHash, signatureData, name, Padding); + using RSA key = ImportKeyData(); + return key.VerifyData(data.Slice(offset, count), signature, algorithm, padding); + } + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyData(data, signature.ToArray(), algorithm, padding); + } + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyData(data.ToByteArray(), signature, algorithm, padding); + } + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyData(data, signature.ToByteArray(), algorithm, padding); + } + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyData(data.Slice(offset, count), signature.ToByteArray(), algorithm, padding); + } + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyData(data, signature.ToByteArray(), algorithm, padding); + } + + /// + /// Determines whether the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified data was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsDataValid(DigitalSignature signature, IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyData(data.ToByteArray(), signature.ToByteArray(), algorithm, padding); + } + + /// + /// Determines whether the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsHashValid(ReadOnlySpan signature, ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyHash(hash, signature, algorithm, padding); + } + + /// + /// Determines whether the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsHashValid(DigitalSignature signature, ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyHash(hash, signature.ToByteArray(), algorithm, padding); + } + + /// + /// Determines whether the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsHashValid(ReadOnlySpan signature, Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyHash(hash.ToByteArray(), signature, algorithm, padding); + } + + /// + /// Determines whether the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// + /// Returns if the specified hash was signed by the RSA cryptographic private key that corresponds to the + /// current RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature; otherwise, . + /// + public bool IsHashValid(DigitalSignature signature, Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + using RSA key = ImportKeyData(); + return key.VerifyHash(hash.ToByteArray(), signature.ToByteArray(), algorithm, padding); + } + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsDataValid(signature, data, algorithm, padding)); + } + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyData(ReadOnlySpan signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsDataValid(signature, data, offset, count, algorithm, padding)); + } + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyData(ReadOnlySpan signature, Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsDataValid(signature, data, algorithm, padding)); + } + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyData(ReadOnlySpan signature, IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsDataValid(signature, data, algorithm, padding)); + } + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyData(DigitalSignature signature, ReadOnlySpan data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsDataValid(signature, data, algorithm, padding)); + } + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The offset into the byte array from which to begin using data. + /// The number of bytes in the array to use as data. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyData(DigitalSignature signature, ReadOnlySpan data, int offset, int count, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsDataValid(signature, data, offset, count, algorithm, padding)); + } + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyData(DigitalSignature signature, Stream data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsDataValid(signature, data, algorithm, padding)); + } + + /// + /// Verifies that the specified data was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed data matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned data to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input data. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyData(DigitalSignature signature, IBinaryConvertible data, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsDataValid(signature, data, algorithm, padding)); + } + + /// + /// Verifies that the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyHash(ReadOnlySpan signature, ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsHashValid(signature, hash, algorithm, padding)); + } + + /// + /// Verifies that the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyHash(DigitalSignature signature, ReadOnlySpan hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsHashValid(signature, hash, algorithm, padding)); + } + + /// + /// Verifies that the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyHash(ReadOnlySpan signature, Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsHashValid(signature, hash, algorithm, padding)); + } + + /// + /// Verifies that the specified hash was signed by the RSA cryptographic private key that corresponds to the current + /// RSA cryptographic public key, and that the signed hash matches the specified cryptographic digital signature. + /// + /// The signature to validate against the current RSA cryptographic public key. + /// The unsigned hash to validate against the current RSA cryptographic public key. + /// The hash algorithm that was used to hash and sign the input hash. + /// The RSA signature padding mode that was used to generate the cryptographic digital signature. + /// If the specified signature could not be verified. + public void VerifyHash(DigitalSignature signature, Hash hash, HashAlgorithmName algorithm, RSASignaturePadding padding) + { + CheckSignature(IsHashValid(signature, hash, algorithm, padding)); + } + + /// + /// Performs a signature check pre-condition that throws a in the event that the specified condition is . + /// + /// The signature condition to check. + /// If the specified condition is . + private static void CheckSignature(bool condition) + { + if (condition) return; + + const string message = "The specified digital signature could not be verified. Either the specified data is incorrect, " + + "or the data was not signed with a private key corresponding to the current public key."; + + throw new CryptographicException(message); } } diff --git a/OnixLabs.Security.Cryptography/RsaPublicKey.cs b/OnixLabs.Security.Cryptography/RsaPublicKey.cs index 8b4798c..418dfc3 100644 --- a/OnixLabs.Security.Cryptography/RsaPublicKey.cs +++ b/OnixLabs.Security.Cryptography/RsaPublicKey.cs @@ -1,39 +1,23 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using System.Security.Cryptography; +using System; namespace OnixLabs.Security.Cryptography; /// -/// Represents an RSA public key. +/// Represents an RSA cryptographic public key. /// -public sealed partial class RsaPublicKey : PublicKey -{ - /// - /// Creates a new instance of the class. - /// - /// The public key data. - /// The hash algorithm type for computing signature data. - /// The for computing signature data. - internal RsaPublicKey(byte[] data, HashAlgorithmType type, RSASignaturePadding padding) : base(data, type) - { - Padding = padding; - } - - /// - /// Gets the for computing signature data. - /// - public RSASignaturePadding Padding { get; } -} +/// The underlying key data of the RSA cryptographic public key. +public sealed partial class RsaPublicKey(ReadOnlySpan keyData) : PublicKey(keyData), IRsaPublicKey; diff --git a/OnixLabs.Security.Cryptography/Salt.Create.cs b/OnixLabs.Security.Cryptography/Salt.Create.cs index a5ee779..f694002 100644 --- a/OnixLabs.Security.Cryptography/Salt.Create.cs +++ b/OnixLabs.Security.Cryptography/Salt.Create.cs @@ -1,11 +1,11 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,17 +19,7 @@ namespace OnixLabs.Security.Cryptography; public readonly partial struct Salt { /// - /// Creates a instance from a array. - /// - /// The array to represent as a salt. - /// A new instance. - public static Salt Create(byte[] value) - { - return new Salt(value); - } - - /// - /// Creates a of the specified length. + /// Creates a new instance of the specified length. /// /// The length of the salt to create. /// Returns a new instance of the specified length. @@ -38,11 +28,11 @@ public static Salt Create(int length) using RandomNumberGenerator generator = RandomNumberGenerator.Create(); byte[] value = new byte[length]; generator.GetBytes(value); - return Create(value); + return new Salt(value); } /// - /// Creates a non-zero of the specified length. + /// Creates a new, non-zero instance of the specified length. /// /// The length of the salt to create. /// Returns a new non-zero instance of the specified length. @@ -51,6 +41,6 @@ public static Salt CreateNonZero(int length) using RandomNumberGenerator generator = RandomNumberGenerator.Create(); byte[] value = new byte[length]; generator.GetNonZeroBytes(value); - return Create(value); + return new Salt(value); } } diff --git a/OnixLabs.Security.Cryptography/Salt.Equatable.cs b/OnixLabs.Security.Cryptography/Salt.Equatable.cs index dd1d9fb..c8d713c 100644 --- a/OnixLabs.Security.Cryptography/Salt.Equatable.cs +++ b/OnixLabs.Security.Cryptography/Salt.Equatable.cs @@ -1,4 +1,4 @@ -// Copyright © 2020 ONIXLabs +// Copyright 2020 ONIXLabs // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,60 +12,59 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System; using System.Linq; using OnixLabs.Core.Linq; namespace OnixLabs.Security.Cryptography; -public readonly partial struct Salt : IEquatable +public readonly partial struct Salt { /// - /// Checks for equality between this instance and another object. + /// Checks whether the current object is equal to another object of the same type. /// - /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// An object to compare with the current object. + /// Returns if the current object is equal to the other parameter; otherwise, . public bool Equals(Salt other) { - return other.Value.SequenceEqual(Value); + return value.SequenceEqual(other.value); } /// - /// Checks for equality between this instance and another object. + /// Checks for equality between the current instance and another object. /// /// The object to check for equality. - /// true if the object is equal to this instance; otherwise, . + /// Returns if the object is equal to the current instance; otherwise, . public override bool Equals(object? obj) { return obj is Salt other && Equals(other); } /// - /// Serves as a hash code function for this instance. + /// Serves as a hash code function for the current instance. /// - /// A hash code for this instance. + /// Returns a hash code for the current instance. public override int GetHashCode() { - return HashCode.Combine(Value.GetContentHashCode()); + return value.GetContentHashCode(); } /// - /// Performs an equality check between two object instances. + /// Performs an equality comparison between two object instances. /// - /// Instance a. - /// Instance b. - /// True if the instances are equal; otherwise, . + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is equal to the right-hand instance; otherwise, . public static bool operator ==(Salt left, Salt right) { return Equals(left, right); } /// - /// Performs an inequality check between two object instances. + /// Performs an inequality comparison between two object instances. /// - /// Instance a. - /// Instance b. - /// True if the instances are not equal; otherwise, . + /// The left-hand instance to compare. + /// The right-hand instance to compare. + /// Returns if the left-hand instance is not equal to the right-hand instance; otherwise, . public static bool operator !=(Salt left, Salt right) { return !Equals(left, right); diff --git a/OnixLabs.Security.Cryptography/Salt.To.cs b/OnixLabs.Security.Cryptography/Salt.To.cs index ac95852..100dd40 100644 --- a/OnixLabs.Security.Cryptography/Salt.To.cs +++ b/OnixLabs.Security.Cryptography/Salt.To.cs @@ -1,60 +1,39 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +using System; using OnixLabs.Core; -using OnixLabs.Core.Text; namespace OnixLabs.Security.Cryptography; public readonly partial struct Salt { /// - /// Returns a array containing the underlying salt data. + /// Gets the underlying representation of the current instance. /// - /// A array containing the underlying salt data. + /// Return the underlying representation of the current instance. public byte[] ToByteArray() { - return Value.Copy(); + return value.Copy(); } /// - /// Creates a from the current salt data. + /// Returns a that represents the current object. /// - /// The of the hash to produce. - /// Returns a of the current salt data. - public Hash ToHash(HashAlgorithmType type) - { - return Hash.ComputeHash(Value, type); - } - - /// - /// Creates a from the current salt data. - /// - /// The of the hash to produce. - /// The length of the hash to produce. - /// Returns a of the current salt data. - public Hash ToHash(HashAlgorithmType type, int length) - { - return Hash.ComputeHash(Value, type, length); - } - - /// - /// Returns a that represents the current object. - /// - /// A that represents the current object. + /// Returns that represents the current object. public override string ToString() { - return Base16.Create(Value).ToString(); + return Convert.ToHexString(value).ToLower(); } } diff --git a/OnixLabs.Security.Cryptography/Salt.cs b/OnixLabs.Security.Cryptography/Salt.cs index 4a8ac72..b773cde 100644 --- a/OnixLabs.Security.Cryptography/Salt.cs +++ b/OnixLabs.Security.Cryptography/Salt.cs @@ -1,37 +1,26 @@ -// Copyright © 2020 ONIXLabs -// +// Copyright 2020 ONIXLabs +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -using OnixLabs.Core; +using System; namespace OnixLabs.Security.Cryptography; /// -/// Represents a cryptographically secure random value. +/// Represents a cryptographically secure random number, otherwise known as a salt value. /// -public readonly partial struct Salt +/// The underlying value of the salt. +public readonly partial struct Salt(ReadOnlySpan value) : ICryptoPrimitive { - /// - /// Initializes a new instance of the struct. - /// - /// The underlying cryptographically secure random value. - private Salt(byte[] value) - { - Value = value.Copy(); - } - - /// - /// Gets the underlying cryptographically secure random value. - /// - private byte[] Value { get; } + private readonly byte[] value = value.ToArray(); } diff --git a/OnixLabs.Security.Cryptography/Sha3.Create.cs b/OnixLabs.Security.Cryptography/Sha3.Create.cs index 0fc5ce1..a6cfaaf 100644 --- a/OnixLabs.Security.Cryptography/Sha3.Create.cs +++ b/OnixLabs.Security.Cryptography/Sha3.Create.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,7 +20,7 @@ public abstract partial class Sha3 /// Creates an instance of the algorithm. /// /// An instance of the algorithm. - public static Sha3 CreateSha3Hash224() + public static Sha3Hash224 CreateSha3Hash224() { return new Sha3Hash224(); } @@ -29,7 +29,7 @@ public static Sha3 CreateSha3Hash224() /// Creates an instance of the algorithm. /// /// An instance of the algorithm. - public static Sha3 CreateSha3Hash256() + public static Sha3Hash256 CreateSha3Hash256() { return new Sha3Hash256(); } @@ -38,7 +38,7 @@ public static Sha3 CreateSha3Hash256() /// Creates an instance of the algorithm. /// /// An instance of the algorithm. - public static Sha3 CreateSha3Hash384() + public static Sha3Hash384 CreateSha3Hash384() { return new Sha3Hash384(); } @@ -47,7 +47,7 @@ public static Sha3 CreateSha3Hash384() /// Creates an instance of the algorithm. /// /// An instance of the algorithm. - public static Sha3 CreateSha3Hash512() + public static Sha3Hash512 CreateSha3Hash512() { return new Sha3Hash512(); } @@ -57,7 +57,7 @@ public static Sha3 CreateSha3Hash512() /// /// The output length of the hash in bytes. /// An instance of the algorithm. - public static Sha3 CreateSha3Shake128(int length) + public static Sha3Shake128 CreateSha3Shake128(int length) { return new Sha3Shake128(length); } @@ -67,7 +67,7 @@ public static Sha3 CreateSha3Shake128(int length) /// /// The output length of the hash in bytes. /// An instance of the algorithm. - public static Sha3 CreateSha3Shake256(int length) + public static Sha3Shake256 CreateSha3Shake256(int length) { return new Sha3Shake256(length); } diff --git a/OnixLabs.Security.Cryptography/Sha3.Permute.cs b/OnixLabs.Security.Cryptography/Sha3.Permute.cs index 142b044..81bdc1c 100644 --- a/OnixLabs.Security.Cryptography/Sha3.Permute.cs +++ b/OnixLabs.Security.Cryptography/Sha3.Permute.cs @@ -29,14 +29,14 @@ private static void Permute(IList state) ulong c0, c1, c2, c3, c4, d0, d1, d2, d3, d4; ulong[] roundConstants = - { + [ 0x0000000000000001, 0x0000000000008082, 0x800000000000808A, 0x8000000080008000, 0x000000000000808B, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008A, 0x0000000000000088, 0x0000000080008009, 0x000000008000000A, 0x000000008000808B, 0x800000000000008B, 0x8000000000008089, 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 0x000000000000800A, 0x800000008000000A, 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 - }; + ]; for (int round = 0; round < hashRounds; round++) { @@ -123,11 +123,11 @@ void Chi() { for (int i = 0; i < 25; i += 5) { - c0 = state[0 + i] ^ ((~state[1 + i]) & state[2 + i]); - c1 = state[1 + i] ^ ((~state[2 + i]) & state[3 + i]); - c2 = state[2 + i] ^ ((~state[3 + i]) & state[4 + i]); - c3 = state[3 + i] ^ ((~state[4 + i]) & state[0 + i]); - c4 = state[4 + i] ^ ((~state[0 + i]) & state[1 + i]); + c0 = state[0 + i] ^ (~state[1 + i] & state[2 + i]); + c1 = state[1 + i] ^ (~state[2 + i] & state[3 + i]); + c2 = state[2 + i] ^ (~state[3 + i] & state[4 + i]); + c3 = state[3 + i] ^ (~state[4 + i] & state[0 + i]); + c4 = state[4 + i] ^ (~state[0 + i] & state[1 + i]); state[0 + i] = c0; state[1 + i] = c1; diff --git a/OnixLabs.Security.Cryptography/Sha3.cs b/OnixLabs.Security.Cryptography/Sha3.cs index 84f0cb3..16be5f7 100644 --- a/OnixLabs.Security.Cryptography/Sha3.cs +++ b/OnixLabs.Security.Cryptography/Sha3.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -42,10 +42,10 @@ public abstract partial class Sha3 : HashAlgorithm /// private readonly int delimiter; - /// - /// The length of the hash in bits. - /// - private readonly int bitLength; + // /// + // /// The length of the hash in bits. + // /// + // private readonly int bitLength; /// /// The state block size. @@ -65,15 +65,15 @@ public abstract partial class Sha3 : HashAlgorithm /// /// The permutable sponge state. /// - private ulong[] state = Array.Empty(); + private ulong[] state = []; /// /// The hash result. /// - private byte[] result = Array.Empty(); + private byte[] result = []; /// - /// Creates a new instance of the class. + /// Initializes a new instance of the class. /// /// The rate in bytes of the sponge state. /// The state delimiter. @@ -82,9 +82,15 @@ protected Sha3(int rateBytes, int delimiter, int bitLength) { this.rateBytes = rateBytes; this.delimiter = delimiter; - this.bitLength = bitLength; + + HashSize = bitLength; } + /// + /// Gets the size, in bits, of the computed hash code. + /// + public override int HashSize { get; } + /// /// Initializes an implementation of the class. /// @@ -94,7 +100,7 @@ public override void Initialize() inputPointer = default; outputPointer = default; state = new ulong[25]; - result = new byte[bitLength / 8]; + result = new byte[HashSize / 8]; } /// @@ -144,7 +150,7 @@ protected override byte[] HashFinal() Buffer.SetByte(state, rateBytes - 1, pad); Permute(state); - int outputBytesLeft = bitLength / 8; + int outputBytesLeft = HashSize / 8; while (outputBytesLeft > 0) { diff --git a/OnixLabs.Security.Cryptography/Sha3Hash224.cs b/OnixLabs.Security.Cryptography/Sha3Hash224.cs index a589334..6000511 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash224.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash224.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ public sealed class Sha3Hash224 : Sha3 private const int BitLength = 224; /// - /// Creates a new instance of the class. + /// Initializes a new instance of the class. /// public Sha3Hash224() : base(RateBytes, HashDelimiter, BitLength) { diff --git a/OnixLabs.Security.Cryptography/Sha3Hash256.cs b/OnixLabs.Security.Cryptography/Sha3Hash256.cs index 0bd953a..a2aa2aa 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash256.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash256.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ public sealed class Sha3Hash256 : Sha3 private const int BitLength = 256; /// - /// Creates a new instance of the class. + /// Initializes a new instance of the class. /// public Sha3Hash256() : base(RateBytes, HashDelimiter, BitLength) { diff --git a/OnixLabs.Security.Cryptography/Sha3Hash384.cs b/OnixLabs.Security.Cryptography/Sha3Hash384.cs index fab67ec..a38d290 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash384.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash384.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ public sealed class Sha3Hash384 : Sha3 private const int BitLength = 384; /// - /// Creates a new instance of the class. + /// Initializes a new instance of the class. /// public Sha3Hash384() : base(RateBytes, HashDelimiter, BitLength) { diff --git a/OnixLabs.Security.Cryptography/Sha3Hash512.cs b/OnixLabs.Security.Cryptography/Sha3Hash512.cs index bfbe7b8..51b8c1c 100644 --- a/OnixLabs.Security.Cryptography/Sha3Hash512.cs +++ b/OnixLabs.Security.Cryptography/Sha3Hash512.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ public sealed class Sha3Hash512 : Sha3 private const int BitLength = 512; /// - /// Creates a new instance of the class. + /// Initializes a new instance of the class. /// public Sha3Hash512() : base(RateBytes, HashDelimiter, BitLength) { diff --git a/OnixLabs.Security.Cryptography/Sha3Shake128.cs b/OnixLabs.Security.Cryptography/Sha3Shake128.cs index 45b6380..4b112c4 100644 --- a/OnixLabs.Security.Cryptography/Sha3Shake128.cs +++ b/OnixLabs.Security.Cryptography/Sha3Shake128.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ public sealed class Sha3Shake128 : Sha3 private const int BitLengthMultiplier = 8; /// - /// Creates a new instance of the class. + /// Initializes a new instance of the class. /// /// The hash output length in bytes. public Sha3Shake128(int length) : base(RateBytes, ShakeDelimiter, length * BitLengthMultiplier) diff --git a/OnixLabs.Security.Cryptography/Sha3Shake256.cs b/OnixLabs.Security.Cryptography/Sha3Shake256.cs index d418a08..e413541 100644 --- a/OnixLabs.Security.Cryptography/Sha3Shake256.cs +++ b/OnixLabs.Security.Cryptography/Sha3Shake256.cs @@ -1,11 +1,11 @@ // Copyright © 2020 ONIXLabs -// +// // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at -// +// // http://www.apache.org/licenses/LICENSE-2.0 -// +// // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -30,7 +30,7 @@ public sealed class Sha3Shake256 : Sha3 private const int BitLengthMultiplier = 8; /// - /// Creates a new instance of the class. + /// Initializes a new instance of the class. /// /// The hash output length in bytes. public Sha3Shake256(int length) : base(RateBytes, ShakeDelimiter, length * BitLengthMultiplier) From a14f3c788ea57aa92ecc3b099ccbf025a285620d Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Mon, 6 May 2024 10:46:34 +0100 Subject: [PATCH 13/14] Updated README (#38) --- README.md | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ec13de8..ca44623 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,34 @@ ![ONIX Labs](https://raw.githubusercontent.com/onix-labs/onixlabs-website/main/src/assets/images/logo/full/original/original-md.png) -# ONIXLabs Core APIs for .NET +# ONIXLabs .NET Library -This repository contains the ONIXLabs Core APIs for .NET +Welcome to the ONIXLabs .NET Library, a comprehensive and meticulously crafted suite of APIs engineered to empower developers and enrich the developer experience. With the ONIXLabs .NET Library, developers gain access to a wealth of tools and resources aimed at streamlining development workflows, enhancing code quality, and fortifying application security. Whether you're a seasoned .NET developer or embarking on your coding journey, ONIXLabs is your trusted companion for building robust and secure software solutions. + +## ONIXLabs Core + +At the heart of the ONIXLabs .NET Library lies the Core module, serving as the bedrock for building resilient and scalable applications. Here, developers will find essential APIs and interfaces meticulously designed to promote code reusability, maintainability, and readability. From foundational interfaces to extension methods enriching object manipulation, ONIXLabs Core sets the stage for seamless development experiences. + +- **Core APIs**: Includes interfaces such as `IValueEquatable`, `IValueComparable`, and `IBinaryConvertible`, providing a foundation for implementing common patterns and functionalities. +- **Extension Methods**: Extends the capabilities of objects, arrays, strings, and enumerables, making data manipulation more intuitive and efficient. +- **Strong Enumeration Pattern**: Offers an implementation of the strong enumeration pattern, for strongly typed enumerations which can be extended with value and associated behaviour. +- **Text Services**: Provides codecs for various encoding schemes like Base16, Base32, Base58, and Base64, along with primitive structs representing these bases for semantic clarity. + +## ONIXLabs Numerics + +Numerical computations are a fundamental aspect of many software applications, often requiring precision, flexibility, and performance. The ONIXLabs Numerics module equips developers with a suite of tools tailored to meet these demands. Whether it's obtaining detailed insights into numeric values or performing complex arithmetic operations, this module empowers developers to tackle numerical challenges with ease and confidence. + +- **NumberInfo**: A versatile struct that provides detailed insights into any numeric value, including unscaled value, scale, significand, exponent, precision, and sign. +- **BigDecimal**: An arbitrary-length decimal number representation leveraging .NET's generic math interfaces. It supports a comprehensive range of arithmetic operations, parsing, conversion, and culture-specific formatting, facilitating precise numerical calculations. +- **Generic Math Extension Methods**: Extends the functionality of numerical types with useful generic math extension methods, enhancing flexibility and productivity in numerical computing tasks. + +## ONIXLabs Cryptography + +In an era marked by increasing cybersecurity threats, robust cryptographic implementations are paramount. The ONIXLabs Cryptography module offers developers a comprehensive set of APIs for handling cryptographic operations securely. From digital signatures and hash functions to Merkle trees and FIPS-202 compliant SHA-3 implementations, developers can leverage ONIXLabs Cryptography to safeguard sensitive data and ensure the integrity and confidentiality of their applications. + +- **DigitalSignature**: Wraps digital signatures, providing a convenient abstraction for cryptographic signature operations. +- **Hash**: Wraps hash functions, facilitating secure hashing of data with ease. +- **MerkleTree**: Represents Merkle trees, enabling efficient verification of data integrity in distributed systems. +- **Salt**: Represents cryptographically secure random numbers, enhancing security in cryptographic operations. +- **Public and Private Key Abstractions**: Offers abstractions for public and private keys, including implementations for RSA and ECDSA, along with functions for signing and verification. +- **SHA-3 Implementation**: A complete, platform-independent, FIPS-202 implementation of SHA-3, including variants like SHA-3 224, 256, 384, 512, SHAKE128, and SHAKE256, ensuring compliance with cryptographic standards. From 41b3bde1640122bbbd9af25f4da3ccff2efcab6c Mon Sep 17 00:00:00 2001 From: Matthew Layton <9935122+MrMatthewLayton@users.noreply.github.com> Date: Mon, 6 May 2024 14:04:59 +0100 Subject: [PATCH 14/14] Updated versions for release. (#39) --- OnixLabs.Core/OnixLabs.Core.csproj | 4 ++-- OnixLabs.Numerics/OnixLabs.Numerics.csproj | 4 ++-- .../OnixLabs.Security.Cryptography.csproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/OnixLabs.Core/OnixLabs.Core.csproj b/OnixLabs.Core/OnixLabs.Core.csproj index 95be286..d9e77e1 100644 --- a/OnixLabs.Core/OnixLabs.Core.csproj +++ b/OnixLabs.Core/OnixLabs.Core.csproj @@ -7,11 +7,11 @@ OnixLabs.Core ONIXLabs ONIXLabs Core API for .NET - 6.0.0 + 7.0.0 en Copyright © ONIXLabs 2020 https://github.com/onix-labs/onixlabs-dotnet - 6.0.0 + 7.0.0 $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb diff --git a/OnixLabs.Numerics/OnixLabs.Numerics.csproj b/OnixLabs.Numerics/OnixLabs.Numerics.csproj index 9a4ac05..b6ab84c 100644 --- a/OnixLabs.Numerics/OnixLabs.Numerics.csproj +++ b/OnixLabs.Numerics/OnixLabs.Numerics.csproj @@ -4,13 +4,13 @@ OnixLabs.Numerics ONIXLabs ONIXLabs Numerics API for .NET - 6.0.0 + 7.0.0 en enable true Copyright © ONIXLabs 2020 https://github.com/onix-labs/onixlabs-dotnet - 6.0.0 + 7.0.0 12 diff --git a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj index af112b2..7dd2cf2 100644 --- a/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj +++ b/OnixLabs.Security.Cryptography/OnixLabs.Security.Cryptography.csproj @@ -4,13 +4,13 @@ OnixLabs.Security.Cryptography ONIXLabs ONIXLabs Cryptography API for .NET - 6.0.0 + 7.0.0 en enable true Copyright © ONIXLabs 2020 https://github.com/onix-labs/onixlabs-dotnet - 6.0.0 + 7.0.0 12