From 2d385ec5e38e3aa887514bc78f75062fcac83d43 Mon Sep 17 00:00:00 2001 From: sakno Date: Sat, 7 Dec 2024 16:11:48 +0200 Subject: [PATCH] Release 5.16.1 --- CHANGELOG.md | 16 +++---- README.md | 16 +++---- .../DotNext.Benchmarks.csproj | 2 +- .../Binary/SevenBitEncodedIntReader.cs | 19 ++++++++ src/DotNext.IO/Buffers/BufferWriter.cs | 8 ++-- src/DotNext.IO/DotNext.IO.csproj | 2 +- src/DotNext.IO/IO/FileReader.Binary.cs | 2 +- src/DotNext.IO/IO/IAsyncBinaryReader.cs | 2 +- .../IO/Pipelines/PipeExtensions.Readers.cs | 2 +- src/DotNext.IO/IO/SequenceReader.cs | 4 +- src/DotNext.IO/IO/StreamExtensions.Readers.cs | 2 +- .../DotNext.Metaprogramming.csproj | 2 +- .../Buffers/Binary/Leb128Tests.cs | 47 +++++++++++++++++++ .../Buffers/BufferWriterTests.cs | 4 +- .../Buffers/ChunkSequenceTests.cs | 2 +- .../Buffers/SpanReaderWriterTests.cs | 2 +- src/DotNext.Tests/DotNext.Tests.csproj | 2 +- src/DotNext.Tests/IO/StreamExtensionsTests.cs | 28 +++++++---- .../TransportServices/TransportTestSuite.cs | 4 +- src/DotNext.Tests/Test.cs | 4 ++ .../DotNext.Threading.csproj | 2 +- src/DotNext.Unsafe/DotNext.Unsafe.csproj | 2 +- src/DotNext/Buffers/Binary/Leb128.cs | 10 ++-- src/DotNext/DotNext.csproj | 2 +- src/DotNext/Numerics/Number.BitVector.cs | 8 ++-- .../DotNext.AspNetCore.Cluster.csproj | 2 +- .../DotNext.Net.Cluster.csproj | 2 +- 27 files changed, 141 insertions(+), 57 deletions(-) create mode 100644 src/DotNext.IO/Buffers/Binary/SevenBitEncodedIntReader.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 299b45c8a..4f56d8661 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1,32 @@ Release Notes ==== -# 12-05-2024 -DotNext 5.16.0 +# 12-07-2024 +DotNext 5.16.1 * Added [LEB128](https://en.wikipedia.org/wiki/LEB128) encoder and decoder as a public API. See `DotNext.Buffers.Binary.Leb128` type for more information * Added `SlideToEnd` method to `SpanWriter` type * Added `IsBitSet` and `SetBit` generic methods to `Number` type * Added `DetachOrCopyBuffer` to `BufferWriterSlim` type -DotNext.Metaprogramming 5.16.0 +DotNext.Metaprogramming 5.16.1 * Updated dependencies -DotNext.Unsafe 5.16.0 +DotNext.Unsafe 5.16.1 * Updated dependencies -DotNext.Threading 5.16.0 +DotNext.Threading 5.16.1 * Async locks with synchronous acquisition methods now throw [LockRecursionException](https://learn.microsoft.com/en-us/dotnet/api/system.threading.lockrecursionexception) if the current thread tries to acquire the lock synchronously and recursively. * Added support of cancellation token to synchronous acquisition methods of `AsyncExclusiveLock` and `AsyncReaderWriterLock` classes * Introduced `LinkTo` method overload that supports multiple cancellation tokens -DotNext.IO 5.16.0 +DotNext.IO 5.16.1 * Introduced `RandomAccessStream` class that represents [Stream](https://learn.microsoft.com/en-us/dotnet/api/system.io.stream) wrapper over the underlying data storage that supports random access pattern * Added extension method for `SpanWriter` that provides length-prefixed string encoding -DotNext.Net.Cluster 5.16.0 +DotNext.Net.Cluster 5.16.1 * Updated dependencies -DotNext.AspNetCore.Cluster 5.16.0 +DotNext.AspNetCore.Cluster 5.16.1 * Updated dependencies # 10-16-2024 diff --git a/README.md b/README.md index b8eb924e5..9cdaa1221 100644 --- a/README.md +++ b/README.md @@ -44,33 +44,33 @@ All these things are implemented in 100% managed code on top of existing .NET AP * [NuGet Packages](https://www.nuget.org/profiles/rvsakno) # What's new -Release Date: 12-05-2024 +Release Date: 12-07-2024 -DotNext 5.16.0 +DotNext 5.16.1 * Added [LEB128](https://en.wikipedia.org/wiki/LEB128) encoder and decoder as a public API. See `DotNext.Buffers.Binary.Leb128` type for more information * Added `SlideToEnd` method to `SpanWriter` type * Added `IsBitSet` and `SetBit` generic methods to `Number` type * Added `DetachOrCopyBuffer` to `BufferWriterSlim` type -DotNext.Metaprogramming 5.16.0 +DotNext.Metaprogramming 5.16.1 * Updated dependencies -DotNext.Unsafe 5.16.0 +DotNext.Unsafe 5.16.1 * Updated dependencies -DotNext.Threading 5.16.0 +DotNext.Threading 5.16.1 * Async locks with synchronous acquisition methods now throw [LockRecursionException](https://learn.microsoft.com/en-us/dotnet/api/system.threading.lockrecursionexception) if the current thread tries to acquire the lock synchronously and recursively. * Added support of cancellation token to synchronous acquisition methods of `AsyncExclusiveLock` and `AsyncReaderWriterLock` classes * Introduced `LinkTo` method overload that supports multiple cancellation tokens -DotNext.IO 5.16.0 +DotNext.IO 5.16.1 * Introduced `RandomAccessStream` class that represents [Stream](https://learn.microsoft.com/en-us/dotnet/api/system.io.stream) wrapper over the underlying data storage that supports random access pattern * Added extension method for `SpanWriter` that provides length-prefixed string encoding -DotNext.Net.Cluster 5.16.0 +DotNext.Net.Cluster 5.16.1 * Updated dependencies -DotNext.AspNetCore.Cluster 5.16.0 +DotNext.AspNetCore.Cluster 5.16.1 * Updated dependencies Changelog for previous versions located [here](./CHANGELOG.md). diff --git a/src/DotNext.Benchmarks/DotNext.Benchmarks.csproj b/src/DotNext.Benchmarks/DotNext.Benchmarks.csproj index 347a50835..3b3546650 100644 --- a/src/DotNext.Benchmarks/DotNext.Benchmarks.csproj +++ b/src/DotNext.Benchmarks/DotNext.Benchmarks.csproj @@ -8,7 +8,7 @@ DotNext DotNext.Program false - 5.16.0 + 5.16.1 .NET Foundation and Contributors .NEXT Family of Libraries Various benchmarks demonstrating performance aspects of .NEXT extensions diff --git a/src/DotNext.IO/Buffers/Binary/SevenBitEncodedIntReader.cs b/src/DotNext.IO/Buffers/Binary/SevenBitEncodedIntReader.cs new file mode 100644 index 000000000..e70b393e1 --- /dev/null +++ b/src/DotNext.IO/Buffers/Binary/SevenBitEncodedIntReader.cs @@ -0,0 +1,19 @@ +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace DotNext.Buffers.Binary; + +[StructLayout(LayoutKind.Auto)] +internal struct SevenBitEncodedIntReader() : IBufferReader, ISupplier +{ + private Leb128 decoder; + private bool incompleted = true; + + readonly int IBufferReader.RemainingBytes => Unsafe.BitCast(incompleted); + + void IReadOnlySpanConsumer.Invoke(ReadOnlySpan source) + => incompleted = decoder.Append(MemoryMarshal.GetReference(source)); + + readonly int ISupplier.Invoke() => (int)decoder.Value; +} \ No newline at end of file diff --git a/src/DotNext.IO/Buffers/BufferWriter.cs b/src/DotNext.IO/Buffers/BufferWriter.cs index 4f03f734f..513ceee3d 100644 --- a/src/DotNext.IO/Buffers/BufferWriter.cs +++ b/src/DotNext.IO/Buffers/BufferWriter.cs @@ -44,15 +44,17 @@ static void WriteSlow(IBufferWriter writer, in ReadOnlySequence value) internal static unsafe int WriteLength(this ref SpanWriter destination, int value, LengthFormat lengthFormat) { - delegate*, int, int> writer = lengthFormat switch + Debug.Assert(value >= 0); + + delegate*, uint, int> writer = lengthFormat switch { LengthFormat.LittleEndian => &ByteBuffer.WriteLittleEndian, LengthFormat.BigEndian => &ByteBuffer.WriteBigEndian, - LengthFormat.Compressed => &ByteBuffer.WriteLeb128, + LengthFormat.Compressed => &ByteBuffer.WriteLeb128, _ => throw new ArgumentOutOfRangeException(nameof(lengthFormat)), }; - return writer(ref destination, value); + return writer(ref destination, (uint)value); } internal static int WriteLength(this IBufferWriter buffer, int length, LengthFormat lengthFormat) diff --git a/src/DotNext.IO/DotNext.IO.csproj b/src/DotNext.IO/DotNext.IO.csproj index bc774d4d7..abca1d422 100644 --- a/src/DotNext.IO/DotNext.IO.csproj +++ b/src/DotNext.IO/DotNext.IO.csproj @@ -11,7 +11,7 @@ .NET Foundation and Contributors .NEXT Family of Libraries - 5.16.0 + 5.16.1 DotNext.IO MIT diff --git a/src/DotNext.IO/IO/FileReader.Binary.cs b/src/DotNext.IO/IO/FileReader.Binary.cs index aec2a275e..562fae07b 100644 --- a/src/DotNext.IO/IO/FileReader.Binary.cs +++ b/src/DotNext.IO/IO/FileReader.Binary.cs @@ -127,7 +127,7 @@ ValueTask IAsyncBinaryReader.ReadAsync(TReader reader, Cancell { LengthFormat.LittleEndian => ReadLittleEndianAsync(token), LengthFormat.BigEndian => ReadBigEndianAsync(token), - LengthFormat.Compressed => ReadAsync>(new(), token), + LengthFormat.Compressed => ReadAsync(new(), token), _ => ValueTask.FromException(new ArgumentOutOfRangeException(nameof(lengthFormat))), }; diff --git a/src/DotNext.IO/IO/IAsyncBinaryReader.cs b/src/DotNext.IO/IO/IAsyncBinaryReader.cs index 938f29a4e..98df447d5 100644 --- a/src/DotNext.IO/IO/IAsyncBinaryReader.cs +++ b/src/DotNext.IO/IO/IAsyncBinaryReader.cs @@ -99,7 +99,7 @@ private async ValueTask ReadAsync(TReader reader, Can { LengthFormat.LittleEndian => ReadLittleEndianAsync(token), LengthFormat.BigEndian => ReadBigEndianAsync(token), - LengthFormat.Compressed => ReadAsync>(new(), token), + LengthFormat.Compressed => ReadAsync(new(), token), _ => ValueTask.FromException(new ArgumentOutOfRangeException(nameof(lengthFormat))), }; diff --git a/src/DotNext.IO/IO/Pipelines/PipeExtensions.Readers.cs b/src/DotNext.IO/IO/Pipelines/PipeExtensions.Readers.cs index d6ea850af..271c8b2ee 100644 --- a/src/DotNext.IO/IO/Pipelines/PipeExtensions.Readers.cs +++ b/src/DotNext.IO/IO/Pipelines/PipeExtensions.Readers.cs @@ -154,7 +154,7 @@ public static ValueTask ReadBigEndianAsync(this PipeReader reader, Cancell { LengthFormat.LittleEndian => reader.ReadLittleEndianAsync(token), LengthFormat.BigEndian => reader.ReadBigEndianAsync(token), - LengthFormat.Compressed => ReadAsync>(reader, new(), token), + LengthFormat.Compressed => ReadAsync(reader, new(), token), _ => ValueTask.FromException(new ArgumentOutOfRangeException(nameof(lengthFormat))), }; diff --git a/src/DotNext.IO/IO/SequenceReader.cs b/src/DotNext.IO/IO/SequenceReader.cs index 7969dc918..8904eb8e7 100644 --- a/src/DotNext.IO/IO/SequenceReader.cs +++ b/src/DotNext.IO/IO/SequenceReader.cs @@ -271,8 +271,8 @@ public MemoryOwner ReadBlock(LengthFormat lengthFormat, MemoryAllocator(); - return Read>(ref parser); + var parser = new SevenBitEncodedIntReader(); + return Read(ref parser); } private int ReadLength(LengthFormat lengthFormat) => lengthFormat switch diff --git a/src/DotNext.IO/IO/StreamExtensions.Readers.cs b/src/DotNext.IO/IO/StreamExtensions.Readers.cs index eef6e8b1b..23e9333f7 100644 --- a/src/DotNext.IO/IO/StreamExtensions.Readers.cs +++ b/src/DotNext.IO/IO/StreamExtensions.Readers.cs @@ -118,7 +118,7 @@ private static unsafe ValueTask ReadLengthAsync(this Stream stream, LengthF return reader(stream, buffer, token); static ValueTask Read7BitEncodedIntAsync(Stream stream, Memory buffer, CancellationToken token) - => ReadAsync>(stream, new(), buffer, token); + => ReadAsync(stream, new(), buffer, token); } /// diff --git a/src/DotNext.Metaprogramming/DotNext.Metaprogramming.csproj b/src/DotNext.Metaprogramming/DotNext.Metaprogramming.csproj index 0bd13365e..144ae4252 100644 --- a/src/DotNext.Metaprogramming/DotNext.Metaprogramming.csproj +++ b/src/DotNext.Metaprogramming/DotNext.Metaprogramming.csproj @@ -8,7 +8,7 @@ true false nullablePublicOnly - 5.16.0 + 5.16.1 .NET Foundation .NEXT Family of Libraries diff --git a/src/DotNext.Tests/Buffers/Binary/Leb128Tests.cs b/src/DotNext.Tests/Buffers/Binary/Leb128Tests.cs index 9316f8f22..627edd60e 100644 --- a/src/DotNext.Tests/Buffers/Binary/Leb128Tests.cs +++ b/src/DotNext.Tests/Buffers/Binary/Leb128Tests.cs @@ -2,6 +2,8 @@ namespace DotNext.Buffers.Binary; +using static IO.StreamSource; + public sealed class Leb128Tests : Test { private static void EncodeDecode(ReadOnlySpan values) @@ -36,4 +38,49 @@ public static void EncodeDecodeEmptyBuffer() False(Leb128.TryGetBytes(42, Span.Empty, out _)); False(Leb128.TryParse(ReadOnlySpan.Empty, out _, out _)); } + + [Theory] + [InlineData(0)] + [InlineData(100500)] + [InlineData(int.MaxValue)] + [InlineData(0x80)] + [InlineData(0x40)] + [InlineData(0x7F)] + public static void CompatibilityWithBinaryReader(int expected) + { + var buffer = new byte[Leb128.MaxSizeInBytes]; + using var reader = new BinaryReader(new ReadOnlyMemory(buffer).AsStream()); + True(Leb128.TryGetBytes((uint)expected, buffer, out _)); + Equal(expected, reader.Read7BitEncodedInt()); + } + + [Theory] + [InlineData(0)] + [InlineData(100500)] + [InlineData(int.MaxValue)] + [InlineData(0x80)] + [InlineData(0x40)] + [InlineData(0x7F)] + public static void CompatibilityWithBinaryWriter(int expected) + { + using var stream = new MemoryStream(Leb128.MaxSizeInBytes); + using var writer = new BinaryWriter(stream); + writer.Write7BitEncodedInt(expected); + + True(Leb128.TryParse(stream.GetBuffer(), out var actual, out _)); + Equal((uint)expected, actual); + } + + [Fact] + public static void DifferenceBetweenSignedAndUnsignedEncoding() + { + Equal(Leb128.MaxSizeInBytes, Leb128.MaxSizeInBytes); + + Span buffer = stackalloc byte[Leb128.MaxSizeInBytes]; + True(Leb128.TryGetBytes(0x7Fu, buffer, out var bytesWritten)); + Equal(1, bytesWritten); + + True(Leb128.TryGetBytes(0x7F, buffer, out bytesWritten)); + Equal(2, bytesWritten); + } } \ No newline at end of file diff --git a/src/DotNext.Tests/Buffers/BufferWriterTests.cs b/src/DotNext.Tests/Buffers/BufferWriterTests.cs index 83163677e..7b2dc4c10 100644 --- a/src/DotNext.Tests/Buffers/BufferWriterTests.cs +++ b/src/DotNext.Tests/Buffers/BufferWriterTests.cs @@ -343,7 +343,7 @@ public static void Rendering() [InlineData(124)] public static void WriteStringBuilder(int stringLength) { - var str = Random.Shared.NextString("abcdefghijklmnopqrstuvwxyz", stringLength); + var str = Random.Shared.NextString(Alphabet, stringLength); var builder = new StringBuilder(); for (var i = 0; i < 3; i++) @@ -364,7 +364,7 @@ public static void WriteStringBuilder(int stringLength) [InlineData(124)] public static void WriteStringBuilder2(int stringLength) { - var str = Random.Shared.NextString("abcdefghijklmnopqrstuvwxyz", stringLength); + var str = Random.Shared.NextString(Alphabet, stringLength); var builder = new StringBuilder(); for (var i = 0; i < 3; i++) diff --git a/src/DotNext.Tests/Buffers/ChunkSequenceTests.cs b/src/DotNext.Tests/Buffers/ChunkSequenceTests.cs index f3818d040..0df4a8037 100644 --- a/src/DotNext.Tests/Buffers/ChunkSequenceTests.cs +++ b/src/DotNext.Tests/Buffers/ChunkSequenceTests.cs @@ -102,7 +102,7 @@ public static void CopyFromSequence() [InlineData(124)] public static void StringBuilderToSequence(int stringLength) { - var str = Random.Shared.NextString("abcdefghijklmnopqrstuvwxyz", stringLength); + var str = Random.Shared.NextString(Alphabet, stringLength); var builder = new StringBuilder(); for (var i = 0; i < 3; i++) diff --git a/src/DotNext.Tests/Buffers/SpanReaderWriterTests.cs b/src/DotNext.Tests/Buffers/SpanReaderWriterTests.cs index c246053ef..d353a0918 100644 --- a/src/DotNext.Tests/Buffers/SpanReaderWriterTests.cs +++ b/src/DotNext.Tests/Buffers/SpanReaderWriterTests.cs @@ -403,7 +403,7 @@ public static void Rendering() [InlineData(124)] public static void WriteStringBuilder(int stringLength) { - var str = Random.Shared.NextString("abcdefghijklmnopqrstuvwxyz", stringLength); + var str = Random.Shared.NextString(Alphabet, stringLength); var builder = new StringBuilder(); for (var i = 0; i < 3; i++) diff --git a/src/DotNext.Tests/DotNext.Tests.csproj b/src/DotNext.Tests/DotNext.Tests.csproj index 41f7a72a8..8bee2de2b 100644 --- a/src/DotNext.Tests/DotNext.Tests.csproj +++ b/src/DotNext.Tests/DotNext.Tests.csproj @@ -6,7 +6,7 @@ latest true false - 5.16.0 + 5.16.1 false .NET Foundation and Contributors .NEXT Family of Libraries diff --git a/src/DotNext.Tests/IO/StreamExtensionsTests.cs b/src/DotNext.Tests/IO/StreamExtensionsTests.cs index 0e148ee21..6b362f652 100644 --- a/src/DotNext.Tests/IO/StreamExtensionsTests.cs +++ b/src/DotNext.Tests/IO/StreamExtensionsTests.cs @@ -101,28 +101,38 @@ public static async Task ReadWriteBlittableTypeAsync() Equal(10M, (await ms.ReadAsync>(buffer)).Value); } - [Fact] - public static async Task BinaryReaderInterop() + [Theory] + [InlineData(7)] + [InlineData(16)] + [InlineData(0x7F)] + [InlineData(0x80)] + public static async Task BinaryReaderInterop(int length) { + var expected = Random.Shared.NextString(Alphabet + AlphabetUpperCase + Numbers, length); using var ms = new MemoryStream(); - await ms.EncodeAsync("ABC".AsMemory(), Encoding.UTF8, LengthFormat.Compressed, new byte[16]); + await ms.EncodeAsync(expected.AsMemory(), Encoding.UTF8, LengthFormat.Compressed, new byte[16]); ms.Position = 0; using var reader = new BinaryReader(ms, Encoding.UTF8, true); - Equal("ABC", reader.ReadString()); + Equal(expected, reader.ReadString()); } - [Fact] - public static async Task BinaryWriterInterop() + [Theory] + [InlineData(7)] + [InlineData(16)] + [InlineData(0x7F)] + [InlineData(0x80)] + public static async Task BinaryWriterInterop(int length) { + var expected = Random.Shared.NextString(Alphabet + AlphabetUpperCase + Numbers, length); using var ms = new MemoryStream(); - using (var writer = new BinaryWriter(ms, Encoding.UTF8, true)) + await using (var writer = new BinaryWriter(ms, Encoding.UTF8, true)) { - writer.Write("ABC"); + writer.Write(expected); } ms.Position = 0; using var result = await ms.DecodeAsync(Encoding.UTF8, LengthFormat.Compressed, new byte[16]); - Equal("ABC", result.ToString()); + Equal(expected, result.Span); } [Fact] diff --git a/src/DotNext.Tests/Net/Cluster/Consensus/Raft/TransportServices/TransportTestSuite.cs b/src/DotNext.Tests/Net/Cluster/Consensus/Raft/TransportServices/TransportTestSuite.cs index d61e782ef..401af8b56 100644 --- a/src/DotNext.Tests/Net/Cluster/Consensus/Raft/TransportServices/TransportTestSuite.cs +++ b/src/DotNext.Tests/Net/Cluster/Consensus/Raft/TransportServices/TransportTestSuite.cs @@ -64,9 +64,9 @@ internal LocalMember(bool smallAmountOfMetadata = false) metadata.Add("a", "b"); else { - const string AllowedChars = "abcdefghijklmnopqrstuvwxyz1234567890"; + const string allowedChars = Alphabet + Numbers; for (var i = 0; i < 20; i++) - metadata.Add(string.Concat("key", i.ToString()), Random.Shared.NextString(AllowedChars, 20)); + metadata.Add(string.Concat("key", i.ToString()), Random.Shared.NextString(allowedChars, 20)); } Metadata = metadata.ToImmutableDictionary(); } diff --git a/src/DotNext.Tests/Test.cs b/src/DotNext.Tests/Test.cs index 5d9c5febf..50631d0f9 100644 --- a/src/DotNext.Tests/Test.cs +++ b/src/DotNext.Tests/Test.cs @@ -8,6 +8,10 @@ namespace DotNext; [ExcludeFromCodeCoverage] public abstract class Test : Assert { + protected const string Alphabet = "abcdefghijklmnopqrstuvwxyz"; + protected const string AlphabetUpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXY"; + protected const string Numbers = "0123456789"; + private protected static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(20); private protected static byte[] RandomBytes(int size) diff --git a/src/DotNext.Threading/DotNext.Threading.csproj b/src/DotNext.Threading/DotNext.Threading.csproj index 9988c2b44..33f32226f 100644 --- a/src/DotNext.Threading/DotNext.Threading.csproj +++ b/src/DotNext.Threading/DotNext.Threading.csproj @@ -7,7 +7,7 @@ true true nullablePublicOnly - 5.16.0 + 5.16.1 .NET Foundation and Contributors .NEXT Family of Libraries diff --git a/src/DotNext.Unsafe/DotNext.Unsafe.csproj b/src/DotNext.Unsafe/DotNext.Unsafe.csproj index 6bdc10e19..5d086a8ea 100644 --- a/src/DotNext.Unsafe/DotNext.Unsafe.csproj +++ b/src/DotNext.Unsafe/DotNext.Unsafe.csproj @@ -7,7 +7,7 @@ enable true true - 5.16.0 + 5.16.1 nullablePublicOnly .NET Foundation and Contributors diff --git a/src/DotNext/Buffers/Binary/Leb128.cs b/src/DotNext/Buffers/Binary/Leb128.cs index 8afd60b49..2eb7503dc 100644 --- a/src/DotNext/Buffers/Binary/Leb128.cs +++ b/src/DotNext/Buffers/Binary/Leb128.cs @@ -11,6 +11,9 @@ namespace DotNext.Buffers.Binary; /// /// Represents encoder and decoder for 7-bit encoded integers. /// +/// +/// Note that encoding of signed and unsigned integers produce different octets. +/// /// The type of the integer. /// LEB128 encoding [StructLayout(LayoutKind.Auto)] @@ -53,7 +56,7 @@ public bool Append(byte b) value |= (T.CreateTruncating(b) & T.CreateTruncating(BitMask)) << shift; shift += 7; - var nextOctetExpected = (b & CarryBit) is not 0; + var nextOctetExpected = Unsafe.BitCast((byte)(b >> 7)); const byte signBit = 0x40; // return back sign bit for signed integers @@ -202,10 +205,9 @@ private void MoveNextSigned() [MethodImpl(MethodImplOptions.AggressiveInlining)] private void MoveNextUnsigned() { - var allBitsSet = T.CreateTruncating(BitMask); - if (value > allBitsSet) + if (value > T.CreateTruncating(BitMask)) { - current = byte.CreateTruncating(value | ~allBitsSet); + current = (byte)(byte.CreateTruncating(value) | CarryBit); value >>>= 7; } else diff --git a/src/DotNext/DotNext.csproj b/src/DotNext/DotNext.csproj index 878d7bfff..43af4e637 100644 --- a/src/DotNext/DotNext.csproj +++ b/src/DotNext/DotNext.csproj @@ -11,7 +11,7 @@ .NET Foundation and Contributors .NEXT Family of Libraries - 5.16.0 + 5.16.1 DotNext MIT diff --git a/src/DotNext/Numerics/Number.BitVector.cs b/src/DotNext/Numerics/Number.BitVector.cs index 9c7a4f578..489bd0d92 100644 --- a/src/DotNext/Numerics/Number.BitVector.cs +++ b/src/DotNext/Numerics/Number.BitVector.cs @@ -17,7 +17,7 @@ public static partial class Number /// if the bit at is set; otherwise, . /// is negative. public static bool IsBitSet(this T number, int position) - where T : struct, IBinaryNumber, IShiftOperators + where T : struct, INumber, IBitwiseOperators, IShiftOperators { ArgumentOutOfRangeException.ThrowIfNegative(position); @@ -34,7 +34,7 @@ public static bool IsBitSet(this T number, int position) /// A modified number. /// is negative. public static T SetBit(this T number, int position, bool value) - where T : struct, IBinaryNumber, IShiftOperators + where T : struct, INumber, IBitwiseOperators, IShiftOperators { ArgumentOutOfRangeException.ThrowIfNegative(position); @@ -51,7 +51,7 @@ public static T SetBit(this T number, int position, bool value) /// A vector of bits. /// A value of type restored from the vector of bits. public static TResult FromBits(this ReadOnlySpan bits) - where TResult : struct, IBinaryNumber, IShiftOperators + where TResult : struct, INumber, IBitwiseOperators, IShiftOperators { var result = TResult.Zero; @@ -72,7 +72,7 @@ public static TResult FromBits(this ReadOnlySpan bits) /// A buffer to be modified. /// has not enough length. public static unsafe void GetBits(this T value, Span bits) - where T : unmanaged, IBinaryNumber, IShiftOperators + where T : unmanaged, INumber, IBitwiseOperators, IShiftOperators { var sizeInBits = sizeof(T) * 8; ArgumentOutOfRangeException.ThrowIfLessThan((uint)bits.Length, (uint)sizeInBits, nameof(bits)); diff --git a/src/cluster/DotNext.AspNetCore.Cluster/DotNext.AspNetCore.Cluster.csproj b/src/cluster/DotNext.AspNetCore.Cluster/DotNext.AspNetCore.Cluster.csproj index d13e48839..977e984dc 100644 --- a/src/cluster/DotNext.AspNetCore.Cluster/DotNext.AspNetCore.Cluster.csproj +++ b/src/cluster/DotNext.AspNetCore.Cluster/DotNext.AspNetCore.Cluster.csproj @@ -8,7 +8,7 @@ true true nullablePublicOnly - 5.16.0 + 5.16.1 .NET Foundation and Contributors .NEXT Family of Libraries diff --git a/src/cluster/DotNext.Net.Cluster/DotNext.Net.Cluster.csproj b/src/cluster/DotNext.Net.Cluster/DotNext.Net.Cluster.csproj index 5e74eb11f..7937404b0 100644 --- a/src/cluster/DotNext.Net.Cluster/DotNext.Net.Cluster.csproj +++ b/src/cluster/DotNext.Net.Cluster/DotNext.Net.Cluster.csproj @@ -8,7 +8,7 @@ enable true nullablePublicOnly - 5.16.0 + 5.16.1 .NET Foundation and Contributors .NEXT Family of Libraries