Skip to content

Add stream wrappers for memory and text based types#562

Merged
SimonCropp merged 3 commits into
mainfrom
Add-Stream-wrappers-for-memory-and-text-based-types
Jun 24, 2026
Merged

Add stream wrappers for memory and text based types#562
SimonCropp merged 3 commits into
mainfrom
Add-Stream-wrappers-for-memory-and-text-based-types

Conversation

@SimonCropp

Copy link
Copy Markdown
Owner

No description provided.

Polyfills StringStream, ReadOnlyMemoryStream, WritableMemoryStream and
ReadOnlySequenceStream from dotnet/runtime#126669.

These types are approved for net11 but are not in the current net11 preview,
so they are gated on `#if FeatureMemory` and remain active on net11. When a
net11 SDK ships the real types, ApiBuilderTests.StreamWrapperBclDetectionTests
fails with the exact change to make in each file: flip the guard to
`#if FeatureMemory && !NET11_0_OR_GREATER` and add a TypeForwardedTo under
`#if NET11_0_OR_GREATER`. The same steps are documented atop each source file.

- ReadOnlyMemoryStream/WritableMemoryStream derive from MemoryStream and delegate
  to the MemoryStream(byte[],int,int,bool,bool) constructor, giving read-only /
  fixed-capacity semantics with GetBuffer throwing and TryGetBuffer returning
  false, without relying on MemoryStream internals unavailable on older TFMs.
- StringStream (non-seekable, never emits a BOM) and ReadOnlySequenceStream
  (seekable) derive from Stream.

Tests run on every framework where FeatureMemory is available; verified compiling
across all 22 TFMs and passing on net11.0 and net48.
@SimonCropp SimonCropp added this to the 10.11.0 milestone Jun 24, 2026
@SimonCropp SimonCropp merged commit 3b17923 into main Jun 24, 2026
5 of 6 checks passed
@SimonCropp SimonCropp deleted the Add-Stream-wrappers-for-memory-and-text-based-types branch June 24, 2026 12:30
This was referenced Jun 24, 2026
This was referenced Jun 25, 2026
SimonCropp added a commit that referenced this pull request Jun 27, 2026
…562) (#563)

* Align stream wrappers with the dotnet 11 implementation (follow-up to #562)

StringStream and ReadOnlySequenceStream diverged from dotnet/runtime#126669
in ways that hurt performance on the cases those types exist for. Bring them
in line and port the PR's tests.

StringStream
- Encode incrementally via a stateful Encoder (fast-path single-shot, spillover
  buffer for sub-scalar reads, final flush) instead of encoding the whole text
  into one buffer on first read. Peak memory is now bounded by the caller's read
  buffer rather than the full encoded length, matching the BCL.
- Span-based Encoder.Convert/Encoding.GetBytes on net core 2.1 / netstandard 2.1+,
  array-based equivalents on older TFMs.

ReadOnlySequenceStream
- Track a SequencePosition cursor alongside the absolute position so Read/ReadByte
  advance from the current segment instead of re-slicing from the start every call
  (was O(segments^2) for multi-segment sequences). Seek/Position reposition the
  cursor forward from the current spot, walking from the start only for back jumps.
- Override CopyTo/CopyToAsync to write segments directly to the destination.
  CopyTo is gated to net core 2.1 / netstandard 2.1+ (Stream.CopyTo(Stream, int)
  is not virtual on older TFMs); CopyToAsync applies everywhere.

ReadOnlyMemoryStream / WritableMemoryStream are unchanged: they are already at
parity for array-backed memory, and matching the BCL for native (non-array)
memory would require MemoryStream internals unavailable outside CoreLib.

Tests
- Port the explicit unit tests from the PR (StringStream encodings, surrogate
  pairs, chunk boundaries, GetMaxByteCount overflow guard, memory-slice/char-array
  ctors; WritableMemoryStream capacity/seek/overwrite cases) into the TUnit suite,
  plus ReadOnlySequenceStream CopyTo/CopyToAsync coverage.

Regenerated Split + assemblySize; public API surface unchanged. Verified across
all 22 TFMs (Consume) and passing on net10.0 and net48.

* Update Directory.Build.props
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant