Commit 51a7727
Port 'WindowsRuntimeBufferExtensions' to 'WinRT.Runtime.dll' (#2298)
* Convert Buffer property to Buffer() method
Change WindowsRuntimePinnedArrayBuffer.Buffer from an internal property getter to a public unsafe Buffer() method (inlined) and update call sites. Also make GetArraySegment public, add an XML <returns> doc and AggressiveInlining, and remove a redundant Debug.Assert for Capacity. Update ABI and WindowsRuntimeBufferMarshal usages to call Buffer(). These changes expose the buffer access method and unify callers to the new signature.
* Add WindowsRuntimeExternalArrayBuffer for external arrays
Introduce WindowsRuntimeExternalArrayBuffer, an internal sealed implementation of IBuffer that wraps an external byte[] with support for offset, length and capacity. Provides Buffer() and GetArraySegment() APIs and a Length setter that enforces capacity (throws E_BOUNDS). Implements a pinning strategy using PinnedGCHandle and caches the pinned data pointer with Interlocked.CompareExchange to be thread-safe, and disposes the pinned handle in a finalizer. Includes debug assertions for constructor parameters and is marked as a managed-only WinRT type.
* Add WindowsRuntimeExternalArrayBuffer marshaller
Introduce ABI support and a custom marshaller for WindowsRuntimeExternalArrayBuffer. Adds TypeMapAssociation, a file-scoped ABI type, and a fixed set of ComInterfaceEntry vtables (IBuffer, IBufferByteAccess, IStringable, IWeakReferenceSource, IMarshal, IAgileObject, IInspectable, IUnknown). Implements a WindowsRuntimeComWrappersMarshallerAttribute that provides vtable computation and GetOrCreateComInterfaceForObject behavior, and a native IBufferByteAccess implementation with an unmanaged Buffer method that returns the underlying byte pointer and converts exceptions to HRESULTs.
* Support WindowsRuntimeExternalArrayBuffer cases
Add handling for the WindowsRuntimeExternalArrayBuffer type in WindowsRuntimeBufferMarshal to extract underlying memory and array segments. Introduces early-return branches that call Buffer()/GetArraySegment() on external array buffers and adds clarifying comments; existing pinned-array handling remains unchanged.
* Flatten Windows.Storage.Streams paths
Remove an extra 'Streams' nesting by relocating several Windows.Storage.Streams files into the Windows.Storage/Streams folder. This cleans up the directory layout to better match namespaces and simplify imports.
Files moved:
- Windows.Storage.Streams/Buffers/WindowsRuntimeBuffer.cs (from ...Streams/Buffers/...)
- Windows.Storage/Streams/IBuffer.cs (from ...Streams/Streams/...)
- Windows.Storage/Streams/IInputStream.cs (from ...Streams/Streams/...)
- Windows.Storage/Streams/IOutputStream.cs (from ...Streams/Streams/...)
- Windows.Storage/Streams/IRandomAccessStream.cs (from ...Streams/Streams/...)
- Windows.Storage/Streams/InputStreamOptions.cs (from ...Streams/Streams/...)
* Use ThrowIfBufferLengthExceedsCapacity helper
Replace the manual bounds check and construction of ArgumentOutOfRangeException in the Length setter with ArgumentOutOfRangeException.ThrowIfBufferLengthExceedsCapacity(value, Capacity). This centralizes validation, simplifies the code, and ensures consistent exception details (including HResult) when the buffer length exceeds capacity.
* Add GetSpan to external and pinned buffers
Introduce ReadOnlySpan<byte> GetSpan() implementations for WindowsRuntimePinnedArrayBuffer and WindowsRuntimeExternalArrayBuffer. Both methods use MemoryMarshal.GetArrayDataReference and Unsafe.Add to create a ReadOnlySpan via MemoryMarshal.CreateReadOnlySpan and are annotated with AggressiveInlining. The pinned variant notes that parameters were validated at construction so offset/capacity checks are skipped; the external variant references the same rationale to avoid extra overhead while providing efficient span access to the buffer data.
* Rename GetSpan to GetSpanForCapacity
Rename WindowsRuntimePinnedArrayBuffer.GetSpan to GetSpanForCapacity to make the semantics explicit: the returned ReadOnlySpan<byte> covers Capacity (not Length). Update WindowsRuntimeExternalArrayBuffer XML doc cref to point to the new member and add a remark documenting the capacity-based length. Method inlining and implementation remain unchanged.
* Add IBuffer AsBuffer extensions for byte[]
Introduce WindowsRuntimeBufferExtensions with three AsBuffer overloads for byte[]: AsBuffer(source), AsBuffer(source, offset, length) and AsBuffer(source, offset, length, capacity). The methods validate arguments and return a WindowsRuntimeExternalArrayBuffer that exposes the byte array as an IBuffer with specified length and capacity. Includes MIT header and preserved commented exception message checks for range/capacity validation.
* Use Span for buffer capacity and add CopyTo
Change ReadOnlySpan<byte> -> Span<byte> for GetSpanForCapacity in WindowsRuntimeExternalArrayBuffer and WindowsRuntimePinnedArrayBuffer to allow mutable access and use MemoryMarshal.CreateSpan. Add a new Argument_InvalidIBufferInstance message. Extend WindowsRuntimeBufferExtensions: adjust AsBuffer overloads to use named args, add CopyTo(ReadOnlySpan<byte>, IBuffer[, uint]) methods to efficiently copy into IBuffer (with GC.KeepAlive and Length update semantics), and add a private GetSpanForCapacity(IBuffer) helper that retrieves a Span<byte> for native, external-array, or pinned-array backed buffers and throws the new argument exception for unsupported IBuffer instances. Also add a few using directives required by the new code.
* Add byte[] CopyTo overloads and improve docs
Refine XML docs for ReadOnlySpan<byte>.CopyTo overloads (singular "value" wording) and add missing <exception> tags documenting ArgumentNullException, ArgumentException and ArgumentOutOfRangeException cases. Introduce two new byte[] CopyTo overloads: CopyTo(byte[] source, IBuffer destination) and CopyTo(byte[] source, int sourceIndex, IBuffer destination, uint destinationIndex, int count). Both delegate to the existing ReadOnlySpan<byte> implementations (using AsSpan) and perform null checks before calling into the span-based logic.
* Add IBuffer-to-Span CopyTo overloads
Add two CopyTo overloads to copy from IBuffer to Span<byte> (full-buffer and ranged variants). Implement argument checks, early-return for zero-length copies, use GetSpanForCapacity(...).Slice for span slicing and call GC.KeepAlive(source) after the copy. Also replace a range-based span slice with explicit Slice, add a pragma to suppress IDE0057, and update XML docs and exception wording to better describe destination capacity requirements.
* Add byte[] overloads for IBuffer.CopyTo
Add two convenience overloads for copying IBuffer contents to byte arrays: CopyTo(this IBuffer, byte[]) and CopyTo(this IBuffer, uint sourceIndex, byte[] destination, int destinationIndex, int count). Both perform null checks and forward to the existing Span-based CopyTo implementation. Also update the XML summary on the Span-based CopyTo to correctly reference Span<T>. These changes make it easier for callers using arrays to copy buffer data without manually creating spans.
* Add IBuffer CopyTo overloads and safety checks
Add two IBuffer.CopyTo overloads to copy entire buffers or a specified range between IBuffer instances, including XML docs. Introduce System.Diagnostics and Debug.Assert checks for int.MaxValue bounds, early-return for zero-length copies, Span-based copy logic, GC.KeepAlive calls, and update destination.Length after copy. Also add Debug.Assert guards in existing copy helpers and argument null checks to improve safety and correctness.
* Add IBuffer.ToArray extension methods
Introduce two ToArray extension overloads for IBuffer: a parameterless variant that copies the entire buffer and an overload that accepts a sourceIndex and count. Both perform null/argument validation, handle a zero-length fast path (returning an empty array), allocate an uninitialized byte[] via GC.AllocateUninitializedArray, and copy data using the buffer's CopyTo method. Some additional range checks (Array.MaxLength and capacity/remaining-space checks) are present but commented out.
* Add IsSameData and TryGetSpan helpers
Introduce IsSameData(IBuffer, IBuffer?) to detect whether two IBuffer instances share the same underlying memory (handles both managed and native-backed buffers). Add TryGetNativeSpanForCapacity and TryGetManagedSpanForCapacity to safely obtain Span<byte> for a buffer's Capacity without throwing/pinning, and refactor GetSpanForCapacity to use these helpers. Document potential exceptions for IBufferByteAccess.Buffer failures on various CopyTo/ToArray APIs and add necessary using/imports and attributes. These changes avoid unnecessary pinning, centralize native/managed span retrieval, and improve diagnostics when interacting with IBuffer internals.
* Add IBuffer.GetByte extension method
Introduce GetByte(this IBuffer, uint) to WindowsRuntimeBufferExtensions with XML docs. The method validates the source is not null, obtains a Span<byte> via GetSpanForCapacity, reads the byte at the specified offset, and calls GC.KeepAlive to ensure the buffer remains alive. Provides a convenient, safe way to read a single byte from an IBuffer instance.
* Add IBuffer-backed MemoryStream wrapper
Introduce WindowsRuntimeBufferMemoryStream, an internal sealed MemoryStream implementation backed by a Windows.Storage.Streams.IBuffer. The stream constructor accepts an IBuffer, a backing byte[] and an offset and initializes the stream length from the buffer. Overrides SetLength, Write (sync and span), WriteAsync (task and ValueTask) and WriteByte to keep the IBuffer.Length in sync with the stream. This supports managed-to-WinRT buffer interop without parameter validation in the constructor.
* Add UnmanagedMemoryStream backed by IBuffer
Introduce WindowsRuntimeBufferUnmanagedMemoryStream: an UnmanagedMemoryStream implementation backed by a native IBuffer. The new class exposes a constructor accepting an IBuffer and native byte* memory, overrides SetLength and various Write APIs (sync/async/Span/byte) to keep the IBuffer.Length in sync, and uses FileAccess.ReadWrite. Also add a private _buffer field (with comment) to WindowsRuntimeBufferMemoryStream.cs. Note: the UnmanagedMemoryStream constructor does not validate parameters and uses unsafe pointer input.
* Add GetArray and IBuffer AsStream helpers
Expose underlying array accessors on WindowsRuntimeExternalArrayBuffer and WindowsRuntimePinnedArrayBuffer (GetArray(out int offset)), and add MemoryStream <-> IBuffer helpers in WindowsRuntimeBufferExtensions: GetWindowsRuntimeBuffer overloads to create IBuffer from MemoryStream, and AsStream to wrap an IBuffer as a Stream (handles array-backed and native buffers). Also add System.IO using and fix inverted logic in GetSpanForCapacity to correctly throw for invalid IBuffer instances. These changes enable sharing memory between MemoryStream and IBuffer and provide a convenient Stream view over IBuffer data.
* Use exception helpers for buffer checks
Add a set of ArgumentException/ArgumentOutOfRange/UnauthorizedAccess helpers to WindowsRuntimeExceptionExtensions and corresponding message constants to WindowsRuntimeExceptionMessages. Replace in-file commented/manual validation checks in WindowsRuntimeBufferExtensions with calls to the new ThrowIf* helpers (e.g. ThrowIfInsufficientArrayElementsAfterOffset, ThrowIfInsufficientBufferCapacity, ThrowIfBufferIndexExceedsCapacity/Length, ThrowIfInsufficientSpaceInSourceBuffer/TargetBuffer, ThrowIfStreamPositionBeyondEndOfStream, ThrowIfBufferLengthExceedsArrayMaxLength, ThrowInvalidIBufferInstance, ThrowInternalBufferAccess). Helpers are annotated for inlining/stack-trace hiding and centralize error text creation for clearer, consistent validation and minor performance improvements.
* Remove WindowsRuntimeBuffer and related files
Delete WinRT buffer implementation and helpers for Windows.Storage.Streams (IBufferByteAccess.cs, IMarshal.cs, IMemoryBufferByteAccess.cs, WindowsRuntimeBuffer.cs, WindowsRuntimeBufferExtensions.cs) and remove their entries from src/cswinrt/cswinrt.vcxproj and cswinrt.vcxproj.filters. Cleans up deprecated/unneeded buffer wrapper code and project file references.
* Fix typo
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Fix typos
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Use BufferOffset exception message and add constant
Replace the incorrect Argument_BufferIndexExceedsLength usage with a new Argument_BufferOffsetExceedsLength in WindowsRuntimeExceptionExtensions to provide a more accurate error for offset checks. Add the corresponding constant message to WindowsRuntimeExceptionMessages.
* Refactor IBuffer unwrap and access helpers
Introduce clearer managed/native unwrapping helpers and simplify buffer logic. Adds TryGetArray and TryGetData to handle managed arrays (array + offset) and native pointers respectively, replaces span-based helpers, and updates equality, span retrieval and stream creation paths to use the new helpers. GetSpanForCapacity now prefers managed arrays, then native data, and throws for unrecognized buffers. Also removes the now-unused ThrowInvalidIBufferInstance helper from WindowsRuntimeExceptionExtensions.cs. These changes reduce low-level unsafe span usage, centralize native access, and make equality/stream logic rely on array/offset or raw pointers.
* Remove unused usings in buffer extensions
Remove unused using directives System.Runtime.CompilerServices and System.Runtime.InteropServices from WindowsRuntimeBufferExtensions.cs to clean up imports. No functional changes; reduces compiler warnings for unused namespaces.
* Add Windows Buffers using; remove attribute
Remove the special-case emission of the TypeMapAssociation assembly attribute from src/cswinrt/main.cpp. Add using Windows.Storage.Buffers and tidy up using directives in StreamOperationsImplementation.cs, WinRtIOHelper.cs and WinRtToNetFxStreamAdapter.cs (also adjust placement of System.Diagnostics.CodeAnalysis). These changes prepare the additions to use Windows.Storage.Buffers types and stop emitting the assembly-level TypeMapAssociation here.
* Remove unused WindowsRuntime usings
Remove the unused System.Runtime.InteropServices.WindowsRuntime using directives from WinRtIOHelper.cs and WinRtToNetFxStreamAdapter.cs. This is a tidy-up to eliminate redundant imports (and related compiler warnings); no functional changes.
* Stub WindowsRuntimeBuffer handling with TODOs
Replace direct WindowsRuntimeBuffer cast and TryGetUnderlyingData usage with null/placeholder assignments and TODO comments in StreamOperationsImplementation.cs. This temporarily disables the optimized managed-array path (the buffer.TryGetUnderlyingData branch) and keeps the generic allocation fallback intact. Restore the original cast and TryGetUnderlyingData calls later to recover the optimized behavior.
* Remove WindowsRuntime using; add Buffers namespace
Remove obsolete System.Runtime.InteropServices.WindowsRuntime using directives from multiple test files and add using Windows.Storage.Buffers where needed. Affected files: FunctionalTests/Async/Program.cs, ObjectLifetimeTests/{App,MainWindow,MyControl,ObjectLifetimePage}.xaml.cs, UnitTest/ApiCompatTests.cs, and UnitTest/TestComponentCSharp_Tests.cs. This updates imports to use Windows.Storage.Buffers for buffer-related types and cleans up unnecessary WindowsRuntime interop using statements.
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>1 parent db15e77 commit 51a7727
34 files changed
Lines changed: 1531 additions & 1353 deletions
File tree
- src
- Tests
- FunctionalTests/Async
- ObjectLifetimeTests
- UnitTest
- WinRT.Runtime2
- ABI/WindowsRuntime.InteropServices/Buffers
- InteropServices
- Buffers
- MemoryStreams
- Properties
- Windows.Storage
- Buffers
- Streams
- cswinrt
- strings/additions/Windows.Storage.Streams
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | 4 | | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
13 | | - | |
14 | 13 | | |
15 | 14 | | |
16 | 15 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | 12 | | |
14 | 13 | | |
15 | 14 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | 5 | | |
7 | 6 | | |
8 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
24 | 25 | | |
25 | 26 | | |
26 | 27 | | |
27 | 28 | | |
28 | | - | |
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
17 | 16 | | |
18 | 17 | | |
19 | 18 | | |
| |||
36 | 35 | | |
37 | 36 | | |
38 | 37 | | |
| 38 | + | |
39 | 39 | | |
40 | 40 | | |
41 | 41 | | |
| |||
src/WinRT.Runtime2/ABI/WindowsRuntime.InteropServices/Buffers/WindowsRuntimeExternalArrayBuffer.cs
Lines changed: 155 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
148 | | - | |
| 148 | + | |
149 | 149 | | |
150 | 150 | | |
151 | 151 | | |
| |||
Lines changed: 85 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
0 commit comments