Skip to content

Commit 3e6ff7c

Browse files
committed
Release 5.1.0
1 parent a0427a7 commit 3e6ff7c

25 files changed

+591
-75
lines changed

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,30 @@
11
Release Notes
22
====
33

4+
# 02-28-2024
5+
<a href="https://www.nuget.org/packages/dotnext/5.1.0">DotNext 5.1.0</a>
6+
* Added `Span.Advance<T>` extension method for spans
7+
* `CollectionType.GetItemType` now correctly recognizes enumerable pattern even if target type doesn't implement `IEnumerable<T>`
8+
9+
<a href="https://www.nuget.org/packages/dotnext.metaprogramming/5.1.0">DotNext.Metaprogramming 5.1.0</a>
10+
* Updated dependencies
11+
12+
<a href="https://www.nuget.org/packages/dotnext.unsafe/5.1.0">DotNext.Unsafe 5.1.0</a>
13+
* Added `UnmanagedMemory.AsMemory` static method that allows to wrap unmanaged pointer into [Memory&lt;T&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.memory-1)
14+
15+
<a href="https://www.nuget.org/packages/dotnext.threading/5.1.0">DotNext.Threading 5.1.0</a>
16+
* Updated dependencies
17+
18+
<a href="https://www.nuget.org/packages/dotnext.io/5.1.0">DotNext.IO 5.1.0</a>
19+
* Merged [225](https://github.com/dotnet/dotNext/pull/225)
20+
* Added `AsUnbufferedStream` extension method for [SafeFileHandle](https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.safehandles.safefilehandle) class
21+
22+
<a href="https://www.nuget.org/packages/dotnext.net.cluster/5.1.0">DotNext.Net.Cluster 5.1.0</a>
23+
* Updated dependencies
24+
25+
<a href="https://www.nuget.org/packages/dotnext.aspnetcore.cluster/5.1.0">DotNext.AspNetCore.Cluster 5.1.0</a>
26+
* Updated dependencies
27+
428
# 02-25-2024
529
<a href="https://www.nuget.org/packages/dotnext/5.0.3">DotNext 5.0.3</a>
630
* Fixed behavior to no-op when `GCLatencyModeScope` is initialized to default

CONTRIBUTING.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ contact [[email protected]](mailto:[email protected]) with
1717
## Branching Model
1818
This repository uses branching model known as [git flow](https://nvie.com/posts/a-successful-git-branching-model/). Use **develop** as the destination branch in your Pull Request.
1919

20+
Since 5.x release, squash commit is used to merge all commits related to the release when moving to `main` branch.
21+
2022
## Backward Compatibility
2123
Contributions must not contain breaking changes such as backward incompatible modification of API signatures. The only exception is a new major version of the library. However, it should pass through code review and discussion.
2224

README.md

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,28 +44,30 @@ All these things are implemented in 100% managed code on top of existing .NET AP
4444
* [NuGet Packages](https://www.nuget.org/profiles/rvsakno)
4545

4646
# What's new
47-
Release Date: 02-25-2024
47+
Release Date: 02-28-2024
4848

49-
<a href="https://www.nuget.org/packages/dotnext/5.0.3">DotNext 5.0.3</a>
50-
* Fixed behavior to no-op when `GCLatencyModeScope` is initialized to default
49+
<a href="https://www.nuget.org/packages/dotnext/5.1.0">DotNext 5.1.0</a>
50+
* Added `Span.Advance<T>` extension method for spans
51+
* `CollectionType.GetItemType` now correctly recognizes enumerable pattern even if target type doesn't implement `IEnumerable<T>`
5152

52-
<a href="https://www.nuget.org/packages/dotnext.metaprogramming/5.0.3">DotNext.Metaprogramming 5.0.3</a>
53+
<a href="https://www.nuget.org/packages/dotnext.metaprogramming/5.1.0">DotNext.Metaprogramming 5.1.0</a>
5354
* Updated dependencies
5455

55-
<a href="https://www.nuget.org/packages/dotnext.unsafe/5.0.3">DotNext.Unsafe 5.0.3</a>
56-
* Updated dependencies
56+
<a href="https://www.nuget.org/packages/dotnext.unsafe/5.1.0">DotNext.Unsafe 5.1.0</a>
57+
* Added `UnmanagedMemory.AsMemory` static method that allows to wrap unmanaged pointer into [Memory&lt;T&gt;](https://learn.microsoft.com/en-us/dotnet/api/system.memory-1)
5758

58-
<a href="https://www.nuget.org/packages/dotnext.threading/5.0.3">DotNext.Threading 5.0.3</a>
59+
<a href="https://www.nuget.org/packages/dotnext.threading/5.1.0">DotNext.Threading 5.1.0</a>
5960
* Updated dependencies
6061

61-
<a href="https://www.nuget.org/packages/dotnext.io/5.0.3">DotNext.IO 5.0.3</a>
62-
* Updated dependencies
62+
<a href="https://www.nuget.org/packages/dotnext.io/5.1.0">DotNext.IO 5.1.0</a>
63+
* Merged [225](https://github.com/dotnet/dotNext/pull/225)
64+
* Added `AsUnbufferedStream` extension method for [SafeFileHandle](https://learn.microsoft.com/en-us/dotnet/api/microsoft.win32.safehandles.safefilehandle) class
6365

64-
<a href="https://www.nuget.org/packages/dotnext.net.cluster/5.0.3">DotNext.Net.Cluster 5.0.3</a>
65-
* Attempt to fix [221](https://github.com/dotnet/dotNext/issues/221)
66+
<a href="https://www.nuget.org/packages/dotnext.net.cluster/5.1.0">DotNext.Net.Cluster 5.1.0</a>
67+
* Updated dependencies
6668

67-
<a href="https://www.nuget.org/packages/dotnext.aspnetcore.cluster/5.0.3">DotNext.AspNetCore.Cluster 5.0.3</a>
68-
* Attempt to fix [221](https://github.com/dotnet/dotNext/issues/221)
69+
<a href="https://www.nuget.org/packages/dotnext.aspnetcore.cluster/5.1.0">DotNext.AspNetCore.Cluster 5.1.0</a>
70+
* Updated dependencies
6971

7072
Changelog for previous versions located [here](./CHANGELOG.md).
7173

src/DotNext.IO/DotNext.IO.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<Authors>.NET Foundation and Contributors</Authors>
1212
<Company />
1313
<Product>.NEXT Family of Libraries</Product>
14-
<VersionPrefix>5.0.3</VersionPrefix>
14+
<VersionPrefix>5.1.0</VersionPrefix>
1515
<VersionSuffix></VersionSuffix>
1616
<AssemblyName>DotNext.IO</AssemblyName>
1717
<PackageLicenseExpression>MIT</PackageLicenseExpression>

src/DotNext.IO/ExceptionMessages.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,6 @@ internal static string DirectoryNotFound(string path)
2323
internal static string WriterInReadMode => (string)Resources.Get();
2424

2525
internal static string NoConsumerProvided => (string)Resources.Get();
26+
27+
internal static string FileHandleClosed => (string)Resources.Get();
2628
}

src/DotNext.IO/ExceptionMessages.restext

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ StreamNotWritable=Stream is not writable
33
StreamNotReadable=Stream is not readable
44
DirectoryNotFound=Directory {0} doesn't exist
55
WriterInReadMode=The writer is in read-only mode. Dispose active memory manager obtained from writer
6-
NoConsumerProvided=No actual consumer is provided
6+
NoConsumerProvided=No actual consumer is provided
7+
FileHandleClosed=The file handle is closed

src/DotNext.IO/IO/StreamExtensions.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Runtime.CompilerServices;
2+
using Microsoft.Win32.SafeHandles;
23

34
namespace DotNext.IO;
45

@@ -25,4 +26,24 @@ internal static void ThrowIfEmpty<T>(in Memory<T> buffer, [CallerArgumentExpress
2526
/// <returns>An object that represents multiple streams as one logical stream.</returns>
2627
public static Stream Combine(this Stream stream, ReadOnlySpan<Stream> others)
2728
=> others is { Length: > 0 } ? new SparseStream([stream, .. others]) : stream;
29+
30+
/// <summary>
31+
/// Creates a stream for the specified file handle.
32+
/// </summary>
33+
/// <remarks>
34+
/// The returned stream doesn't own the handle.
35+
/// </remarks>
36+
/// <param name="handle">The file handle.</param>
37+
/// <param name="access">Desired access to the file via stream.</param>
38+
/// <returns>The unbuffered file stream.</returns>
39+
/// <exception cref="ArgumentNullException"><paramref name="handle"/> is <see langword="null"/>.</exception>
40+
/// <exception cref="ArgumentException"><paramref name="handle"/> is closed or invalid.</exception>
41+
public static Stream AsUnbufferedStream(this SafeFileHandle handle, FileAccess access)
42+
{
43+
ArgumentNullException.ThrowIfNull(handle);
44+
45+
return handle is { IsInvalid: false, IsClosed: false }
46+
? new UnbufferedFileStream(handle, access)
47+
: throw new ArgumentException(ExceptionMessages.FileHandleClosed, nameof(handle));
48+
}
2849
}

src/DotNext.IO/IO/StreamSegment.cs

Lines changed: 30 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,16 @@
88
/// <remarks>
99
/// The segmentation is supported only for seekable streams.
1010
/// </remarks>
11-
public sealed class StreamSegment : Stream, IFlushable
11+
/// <param name="stream">The underlying stream represented by the segment.</param>
12+
/// <param name="leaveOpen"><see langword="true"/> to leave <paramref name="stream"/> open after the object is disposed; otherwise, <see langword="false"/>.</param>
13+
public sealed class StreamSegment(Stream stream, bool leaveOpen = true) : Stream, IFlushable
1214
{
13-
private readonly bool leaveOpen;
14-
private long length, offset;
15-
16-
/// <summary>
17-
/// Initializes a new segment of the specified stream.
18-
/// </summary>
19-
/// <param name="stream">The underlying stream represented by the segment.</param>
20-
/// <param name="leaveOpen"><see langword="true"/> to leave <paramref name="stream"/> open after the object is disposed; otherwise, <see langword="false"/>.</param>
21-
/// <exception cref="ArgumentNullException"><paramref name="stream"/> is <see langword="null"/>.</exception>
22-
public StreamSegment(Stream stream, bool leaveOpen = true)
23-
{
24-
BaseStream = stream ?? throw new ArgumentNullException(nameof(stream));
25-
length = stream.Length;
26-
offset = 0L;
27-
this.leaveOpen = leaveOpen;
28-
}
15+
private long length = stream.Length, offset;
2916

3017
/// <summary>
3118
/// Gets underlying stream.
3219
/// </summary>
33-
public Stream BaseStream { get; }
20+
public Stream BaseStream => stream;
3421

3522
/// <summary>
3623
/// Establishes segment bounds.
@@ -40,28 +27,28 @@ public StreamSegment(Stream stream, bool leaveOpen = true)
4027
/// </remarks>
4128
/// <param name="offset">The offset in the underlying stream.</param>
4229
/// <param name="length">The length of the segment.</param>
43-
/// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is larger than the reamining length of the underlying stream; or <paramref name="offset"/> if greater than the length of the underlying stream.</exception>
30+
/// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is larger than the remaining length of the underlying stream; or <paramref name="offset"/> if greater than the length of the underlying stream.</exception>
4431
public void Adjust(long offset, long length)
4532
{
46-
ArgumentOutOfRangeException.ThrowIfGreaterThan((ulong)offset, (ulong)BaseStream.Length, nameof(offset));
47-
ArgumentOutOfRangeException.ThrowIfGreaterThan((ulong)offset, (ulong)(BaseStream.Length - offset), nameof(length));
33+
ArgumentOutOfRangeException.ThrowIfGreaterThan((ulong)offset, (ulong)stream.Length, nameof(offset));
34+
ArgumentOutOfRangeException.ThrowIfGreaterThan((ulong)length, (ulong)(stream.Length - offset), nameof(length));
4835

4936
this.length = length;
5037
this.offset = offset;
51-
BaseStream.Position = offset;
38+
stream.Position = offset;
5239
}
5340

5441
/// <summary>
5542
/// Gets a value indicating whether the current stream supports reading.
5643
/// </summary>
5744
/// <value><see langword="true"/> if the stream supports reading; otherwise, <see langword="false"/>.</value>
58-
public override bool CanRead => BaseStream.CanRead;
45+
public override bool CanRead => stream.CanRead;
5946

6047
/// <summary>
6148
/// Gets a value indicating whether the current stream supports seeking.
6249
/// </summary>
6350
/// <value><see langword="true"/> if the stream supports seeking; otherwise, <see langword="false"/>.</value>
64-
public override bool CanSeek => BaseStream.CanSeek;
51+
public override bool CanSeek => stream.CanSeek;
6552

6653
/// <summary>
6754
/// Gets a value indicating whether the current stream supports writing.
@@ -75,29 +62,29 @@ public void Adjust(long offset, long length)
7562
/// <inheritdoc/>
7663
public override long Position
7764
{
78-
get => BaseStream.Position - offset;
65+
get => stream.Position - offset;
7966
set
8067
{
8168
ArgumentOutOfRangeException.ThrowIfGreaterThan((ulong)value, (ulong)length, nameof(value));
8269

83-
BaseStream.Position = offset + value;
70+
stream.Position = offset + value;
8471
}
8572
}
8673

8774
private long RemainingBytes => length - Position;
8875

8976
/// <inheritdoc/>
90-
public override void Flush() => BaseStream.Flush();
77+
public override void Flush() => stream.Flush();
9178

9279
/// <inheritdoc/>
93-
public override Task FlushAsync(CancellationToken token = default) => BaseStream.FlushAsync(token);
80+
public override Task FlushAsync(CancellationToken token = default) => stream.FlushAsync(token);
9481

9582
/// <inheritdoc/>
96-
public override bool CanTimeout => BaseStream.CanTimeout;
83+
public override bool CanTimeout => stream.CanTimeout;
9784

9885
/// <inheritdoc/>
9986
public override int ReadByte()
100-
=> Position < length ? BaseStream.ReadByte() : -1;
87+
=> Position < length ? stream.ReadByte() : -1;
10188

10289
/// <inheritdoc/>
10390
public override void WriteByte(byte value) => throw new NotSupportedException();
@@ -107,30 +94,30 @@ public override int Read(byte[] buffer, int offset, int count)
10794
{
10895
ValidateBufferArguments(buffer, offset, count);
10996

110-
return BaseStream.Read(buffer, offset, (int)Math.Min(count, RemainingBytes));
97+
return stream.Read(buffer, offset, (int)Math.Min(count, RemainingBytes));
11198
}
11299

113100
/// <inheritdoc/>
114101
public override int Read(Span<byte> buffer)
115-
=> BaseStream.Read(buffer.TrimLength(int.CreateSaturating(RemainingBytes)));
102+
=> stream.Read(buffer.TrimLength(int.CreateSaturating(RemainingBytes)));
116103

117104
/// <inheritdoc/>
118105
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback? callback, object? state)
119106
{
120107
count = (int)Math.Min(count, RemainingBytes);
121-
return BaseStream.BeginRead(buffer, offset, count, callback, state);
108+
return stream.BeginRead(buffer, offset, count, callback, state);
122109
}
123110

124111
/// <inheritdoc/>
125-
public override int EndRead(IAsyncResult asyncResult) => BaseStream.EndRead(asyncResult);
112+
public override int EndRead(IAsyncResult asyncResult) => stream.EndRead(asyncResult);
126113

127114
/// <inheritdoc/>
128115
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken token = default)
129-
=> BaseStream.ReadAsync(buffer, offset, (int)Math.Min(count, RemainingBytes), token);
116+
=> stream.ReadAsync(buffer, offset, (int)Math.Min(count, RemainingBytes), token);
130117

131118
/// <inheritdoc/>
132119
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken token = default)
133-
=> BaseStream.ReadAsync(buffer.TrimLength(int.CreateSaturating(RemainingBytes)), token);
120+
=> stream.ReadAsync(buffer.TrimLength(int.CreateSaturating(RemainingBytes)), token);
134121

135122
/// <inheritdoc/>
136123
public override long Seek(long offset, SeekOrigin origin)
@@ -155,7 +142,7 @@ public override long Seek(long offset, SeekOrigin origin)
155142
/// <inheritdoc/>
156143
public override void SetLength(long value)
157144
{
158-
ArgumentOutOfRangeException.ThrowIfGreaterThan((ulong)value, (ulong)(BaseStream.Length - BaseStream.Position), nameof(value));
145+
ArgumentOutOfRangeException.ThrowIfGreaterThan((ulong)value, (ulong)(stream.Length - stream.Position), nameof(value));
159146

160147
length = value;
161148
}
@@ -183,30 +170,30 @@ public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, As
183170
/// <inheritdoc/>
184171
public override int ReadTimeout
185172
{
186-
get => BaseStream.ReadTimeout;
187-
set => BaseStream.ReadTimeout = value;
173+
get => stream.ReadTimeout;
174+
set => stream.ReadTimeout = value;
188175
}
189176

190177
/// <inheritdoc/>
191178
public override int WriteTimeout
192179
{
193-
get => BaseStream.WriteTimeout;
194-
set => BaseStream.WriteTimeout = value;
180+
get => stream.WriteTimeout;
181+
set => stream.WriteTimeout = value;
195182
}
196183

197184
/// <inheritdoc/>
198185
protected override void Dispose(bool disposing)
199186
{
200187
if (disposing && !leaveOpen)
201-
BaseStream.Dispose();
188+
stream.Dispose();
202189
base.Dispose(disposing);
203190
}
204191

205192
/// <inheritdoc/>
206193
public override async ValueTask DisposeAsync()
207194
{
208195
if (!leaveOpen)
209-
await BaseStream.DisposeAsync().ConfigureAwait(false);
196+
await stream.DisposeAsync().ConfigureAwait(false);
210197
await base.DisposeAsync().ConfigureAwait(false);
211198
}
212199
}

0 commit comments

Comments
 (0)