Add Stream wrappers for memory and text-based types - #126669

Merged
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api
Jun 24, 2026
Merged

Add Stream wrappers for memory and text-based types#126669
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api

Conversation

@ViveliDuCh

@ViveliDuChViveliDuCh commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fixes#82801

Introduces standardized stream wrappers for text and memory types as public sealed classes (StringStream, ReadOnlyMemoryStream, WritableMemoryStream, and ReadOnlySequenceStream ) as approved in API review (video).

What's included

  • StringStream (System.IO, CoreLib): non-seekable, read-only stream that encodes string or ReadOnlyMemory<char> on-the-fly. Encoding is required (no default). Never emits BOMs.
  • ReadOnlyMemoryStream (System.IO, CoreLib): seekable, read-only stream over ReadOnlyMemory<byte>
  • WritableMemoryStream (System.IO, CoreLib): seekable, read-write stream over Memory<byte> with fixed capacity
  • ReadOnlySequenceStream (System.Buffers, System.Memory): seekable, read-only stream over ReadOnlySequence<byte>
  • Ref assembly updates for System.Runtime and System.Memory
  • Updated 3 internal call sites (ReadOnlyMemoryContent, XmlPreloadedResolver, JsonXmlDataContract) to use the new types
  • Conformance and behavioral tests for all 4 types

Implementation notes

  • All types are public sealed with direct constructors: the review moved away from factory methods on Stream to avoid derived-type IntelliSense noise
  • StringStream encodes directly into the caller's buffer in Read() rather than using an internal byte buffer
  • ReadOnlyMemoryStream and WritableMemoryStream derive from MemoryStream.
  • TryGetBuffer returns false and GetBuffer throws on the memory stream types (no publiclyVisible support for now)

Limitations

  • The internal shared-sourceReadOnlyMemoryStream in Common/ cannot be fully replaced:
    • System.Memory.Data multi-targets netstandard2.0 where the new public type doesn't exist.
    • System.Net.Http (net11.0 only) can adopt it directly.

Follow-up work

  • IBufferWriter<byte>Stream wrapper (separate proposal per #100434)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces new standardized Stream wrapper types across CoreLib and System.Memory, aligning with the approved API shape from #82801 and updating a few internal call sites to use the new wrappers.

Changes:

  • Added new public sealed stream wrappers: StringStream, ReadOnlyMemoryStream, WritableMemoryStream (CoreLib) and ReadOnlySequenceStream (System.Memory).
  • Updated reference assemblies and project files to expose/compile the new APIs.
  • Added conformance + targeted behavioral tests, and updated select internal consumers to use StringStream.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/IO/StringStream.csImplements the new StringStream API (read-only, non-seekable, on-the-fly encoding).
src/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.csImplements seekable read-only stream over ReadOnlyMemory<byte>.
src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csImplements seekable fixed-capacity read/write stream over Memory<byte>.
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsWires new CoreLib stream wrapper source files into the build.
src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAdds a new resource string entry (currently appears unused).
src/libraries/System.Runtime/ref/System.Runtime.csUpdates public API surface to include the new stream wrapper types (and a small ref signature normalization change).
src/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csprojIncludes the new test files in the System.IO test project.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamConformanceTests.csAdds conformance coverage for StringStream (string + ReadOnlyMemory<char> overloads).
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAdds targeted StringStream(string, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAdds targeted StringStream(ReadOnlyMemory<char>, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAdds conformance coverage for ReadOnlyMemoryStream.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamTests.csAdds targeted ReadOnlyMemoryStream behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAdds conformance coverage for WritableMemoryStream (with some overridden tests).
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csAdds targeted WritableMemoryStream behavioral tests.
src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csImplements ReadOnlySequenceStream over ReadOnlySequence<byte>.
src/libraries/System.Memory/src/System.Memory.csprojIncludes the new ReadOnlySequenceStream source file in System.Memory.
src/libraries/System.Memory/src/Resources/Strings.resxAdds SR strings needed for stream-like exception messages in System.Memory.
src/libraries/System.Memory/ref/System.Memory.csAdds ReadOnlySequenceStream to the System.Memory ref surface.
src/libraries/System.Memory/tests/System.Memory.Tests.csprojAdds tests for ReadOnlySequenceStream and references StreamConformanceTests.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStreamTests.csAdds targeted behavioral tests for multi-segment ReadOnlySequenceStream scenarios.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStream.ConformanceTests.csAdds conformance coverage for ReadOnlySequenceStream.
src/libraries/System.Private.Xml/src/System/Xml/Resolvers/XmlPreloadedResolver.csSwitches internal string-to-stream conversion to StringStream.
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csSwitches internal string-to-stream conversion to StringStream.
Comments suppressed due to low confidence (1)

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.cs:38

  • Variable is still named 'memoryStream' but the implementation is now StringStream (not a MemoryStream). Rename the local to avoid implying the stream is seekable/in-memory-buffered (e.g., 'xmlContentStream').
 Stream memoryStream = new StringStream(xmlContent, Encoding.UTF8);
object? xmlValue;
XmlDictionaryReaderQuotas? quotas = ((JsonReaderDelegator)jsonReader).ReaderQuotas;
if (quotas == null)
{
xmlValue = dataContractSerializer.ReadObject(memoryStream);

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/ref/System.Runtime.cs
Comment threadsrc/libraries/System.Private.CoreLib/src/Resources/Strings.resx Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Memory/ref/System.Memory.cs
CopilotAI review requested due to automatic review settings April 9, 2026 08:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csproj Outdated
Comment threadsrc/libraries/System.Memory/src/System.Memory.csproj Outdated
Comment threadsrc/libraries/System.Memory/tests/System.Memory.Tests.csproj Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings April 13, 2026 19:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings June 23, 2026 23:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@SimonCropp

Copy link
Copy Markdown
Contributor

awesome. that .net preview will this be in?

SimonCropp added a commit to SimonCropp/Polyfill that referenced this pull request Jun 24, 2026
* Add Stream wrappers for memory and text-based types
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.
* .
@jozkee

Copy link
Copy Markdown
Member

/backport to release/11.0-preview6

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview6 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@jozkee backporting to release/11.0-preview6 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: First API proposal implementationUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/ref/System.Memory.csM	src/libraries/System.Memory/tests/System.Memory.Tests.csprojM	src/libraries/System.Private.CoreLib/src/Resources/Strings.resxM	src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsM	src/libraries/System.Runtime/ref/System.Runtime.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/ref/System.Memory.csAuto-merging src/libraries/System.Memory/tests/System.Memory.Tests.csprojAuto-merging src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAuto-merging src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsAuto-merging src/libraries/System.Runtime/ref/System.Runtime.csApplying: API replacements in production codeApplying: Implementation update based on latest API Review final consensusApplying: Address PR feedback. MemoryStream base change. Spillover buffer for Convert edge case. Flush strategy update.Applying: Address PR feedbackApplying: Address PR feedback: fix StringStream flush offset, WritableMemoryStream length/seek semantics, ReadOnlySequenceStream safety, and consolidate testsApplying: Address PR feedback: remove redundant code, improve test coverage and structureUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csM	src/libraries/System.Net.Http/src/System.Net.Http.csprojM	src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csM	src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csM	src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csAuto-merging src/libraries/System.Net.Http/src/System.Net.Http.csprojAuto-merging src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csAuto-merging src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csCONFLICT (content): Merge conflict in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0007 Address PR feedback: remove redundant code, improve test coverage and structureError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

jozkee pushed a commit that referenced this pull request Jun 25, 2026
… types (#129811)
Backport of #126669 to
release/11.0-preview6. See that PR for full details.
Adds new public stream wrapper APIs (`StringStream`,
`ReadOnlyMemoryStream`, `WritableMemoryStream`,
`ReadOnlySequenceStream`).
Fixes#82801.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 25, 2026
SimonCropp added a commit to SimonCropp/Polyfill 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
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Fixes#82801
Introduces standardized stream wrappers for text and memory types as
public sealed classes (`StringStream`, `ReadOnlyMemoryStream`,
`WritableMemoryStream`, and `ReadOnlySequenceStream` ) as approved in
[API
review](#82801 (comment))
([video](https://www.youtube.com/watch?v=T7xc7rARCEw&t=0h9m41s)).
### What's included
- `StringStream` (`System.IO`, CoreLib): non-seekable, read-only stream
that encodes `string` or `ReadOnlyMemory<char>` on-the-fly. Encoding is
required (no default). Never emits BOMs.
- `ReadOnlyMemoryStream` (`System.IO`, CoreLib): seekable, read-only
stream over `ReadOnlyMemory<byte>`
- `WritableMemoryStream` (`System.IO`, CoreLib): seekable, read-write
stream over `Memory<byte>` with fixed capacity
- `ReadOnlySequenceStream` (`System.Buffers`, System.Memory): seekable,
read-only stream over `ReadOnlySequence<byte>`
- Ref assembly updates for `System.Runtime` and `System.Memory`
- Updated 3 internal call sites (`ReadOnlyMemoryContent`,
`XmlPreloadedResolver`, `JsonXmlDataContract`) to use the new types
- Conformance and behavioral tests for all 4 types
### Implementation notes
- All types are `public sealed` with direct constructors: the review
moved away from factory methods on `Stream` to avoid derived-type
IntelliSense noise
- `StringStream` encodes directly into the caller's buffer in `Read()`
rather than using an internal byte buffer
- `ReadOnlyMemoryStream` and `WritableMemoryStream` derive from
`MemoryStream`.
- `TryGetBuffer` returns false and `GetBuffer` throws on the memory
stream types (no `publiclyVisible` support for now)
### Limitations
- The internal
[shared-source](https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/ReadOnlyMemoryStream.cs)
`ReadOnlyMemoryStream` in `Common/` cannot be fully replaced:
- `System.Memory.Data` multi-targets `netstandard2.0` where the new
public type doesn't exist.
- `System.Net.Http` (net11.0 only) can adopt it directly.
### Follow-up work
- `IBufferWriter<byte>` → `Stream` wrapper (separate proposal per
[#100434](#100434))
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add Stream wrappers for memory and text-based types

8 participants

@ViveliDuCh@SimonCropp@jozkee@stephentoub@adamsitnik@bartonjs@tarekgh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add Stream wrappers for memory and text-based types - #126669

Merged
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api
Jun 24, 2026
Merged

Add Stream wrappers for memory and text-based types#126669
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api

Conversation

@ViveliDuCh

@ViveliDuChViveliDuCh commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fixes#82801

Introduces standardized stream wrappers for text and memory types as public sealed classes (StringStream, ReadOnlyMemoryStream, WritableMemoryStream, and ReadOnlySequenceStream ) as approved in API review (video).

What's included

  • StringStream (System.IO, CoreLib): non-seekable, read-only stream that encodes string or ReadOnlyMemory<char> on-the-fly. Encoding is required (no default). Never emits BOMs.
  • ReadOnlyMemoryStream (System.IO, CoreLib): seekable, read-only stream over ReadOnlyMemory<byte>
  • WritableMemoryStream (System.IO, CoreLib): seekable, read-write stream over Memory<byte> with fixed capacity
  • ReadOnlySequenceStream (System.Buffers, System.Memory): seekable, read-only stream over ReadOnlySequence<byte>
  • Ref assembly updates for System.Runtime and System.Memory
  • Updated 3 internal call sites (ReadOnlyMemoryContent, XmlPreloadedResolver, JsonXmlDataContract) to use the new types
  • Conformance and behavioral tests for all 4 types

Implementation notes

  • All types are public sealed with direct constructors: the review moved away from factory methods on Stream to avoid derived-type IntelliSense noise
  • StringStream encodes directly into the caller's buffer in Read() rather than using an internal byte buffer
  • ReadOnlyMemoryStream and WritableMemoryStream derive from MemoryStream.
  • TryGetBuffer returns false and GetBuffer throws on the memory stream types (no publiclyVisible support for now)

Limitations

  • The internal shared-sourceReadOnlyMemoryStream in Common/ cannot be fully replaced:
    • System.Memory.Data multi-targets netstandard2.0 where the new public type doesn't exist.
    • System.Net.Http (net11.0 only) can adopt it directly.

Follow-up work

  • IBufferWriter<byte>Stream wrapper (separate proposal per #100434)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces new standardized Stream wrapper types across CoreLib and System.Memory, aligning with the approved API shape from #82801 and updating a few internal call sites to use the new wrappers.

Changes:

  • Added new public sealed stream wrappers: StringStream, ReadOnlyMemoryStream, WritableMemoryStream (CoreLib) and ReadOnlySequenceStream (System.Memory).
  • Updated reference assemblies and project files to expose/compile the new APIs.
  • Added conformance + targeted behavioral tests, and updated select internal consumers to use StringStream.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/IO/StringStream.csImplements the new StringStream API (read-only, non-seekable, on-the-fly encoding).
src/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.csImplements seekable read-only stream over ReadOnlyMemory<byte>.
src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csImplements seekable fixed-capacity read/write stream over Memory<byte>.
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsWires new CoreLib stream wrapper source files into the build.
src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAdds a new resource string entry (currently appears unused).
src/libraries/System.Runtime/ref/System.Runtime.csUpdates public API surface to include the new stream wrapper types (and a small ref signature normalization change).
src/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csprojIncludes the new test files in the System.IO test project.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamConformanceTests.csAdds conformance coverage for StringStream (string + ReadOnlyMemory<char> overloads).
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAdds targeted StringStream(string, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAdds targeted StringStream(ReadOnlyMemory<char>, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAdds conformance coverage for ReadOnlyMemoryStream.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamTests.csAdds targeted ReadOnlyMemoryStream behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAdds conformance coverage for WritableMemoryStream (with some overridden tests).
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csAdds targeted WritableMemoryStream behavioral tests.
src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csImplements ReadOnlySequenceStream over ReadOnlySequence<byte>.
src/libraries/System.Memory/src/System.Memory.csprojIncludes the new ReadOnlySequenceStream source file in System.Memory.
src/libraries/System.Memory/src/Resources/Strings.resxAdds SR strings needed for stream-like exception messages in System.Memory.
src/libraries/System.Memory/ref/System.Memory.csAdds ReadOnlySequenceStream to the System.Memory ref surface.
src/libraries/System.Memory/tests/System.Memory.Tests.csprojAdds tests for ReadOnlySequenceStream and references StreamConformanceTests.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStreamTests.csAdds targeted behavioral tests for multi-segment ReadOnlySequenceStream scenarios.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStream.ConformanceTests.csAdds conformance coverage for ReadOnlySequenceStream.
src/libraries/System.Private.Xml/src/System/Xml/Resolvers/XmlPreloadedResolver.csSwitches internal string-to-stream conversion to StringStream.
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csSwitches internal string-to-stream conversion to StringStream.
Comments suppressed due to low confidence (1)

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.cs:38

  • Variable is still named 'memoryStream' but the implementation is now StringStream (not a MemoryStream). Rename the local to avoid implying the stream is seekable/in-memory-buffered (e.g., 'xmlContentStream').
 Stream memoryStream = new StringStream(xmlContent, Encoding.UTF8);
object? xmlValue;
XmlDictionaryReaderQuotas? quotas = ((JsonReaderDelegator)jsonReader).ReaderQuotas;
if (quotas == null)
{
xmlValue = dataContractSerializer.ReadObject(memoryStream);

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/ref/System.Runtime.cs
Comment threadsrc/libraries/System.Private.CoreLib/src/Resources/Strings.resx Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Memory/ref/System.Memory.cs
CopilotAI review requested due to automatic review settings April 9, 2026 08:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csproj Outdated
Comment threadsrc/libraries/System.Memory/src/System.Memory.csproj Outdated
Comment threadsrc/libraries/System.Memory/tests/System.Memory.Tests.csproj Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings April 13, 2026 19:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings June 23, 2026 23:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@SimonCropp

Copy link
Copy Markdown
Contributor

awesome. that .net preview will this be in?

SimonCropp added a commit to SimonCropp/Polyfill that referenced this pull request Jun 24, 2026
* Add Stream wrappers for memory and text-based types
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.
* .
@jozkee

Copy link
Copy Markdown
Member

/backport to release/11.0-preview6

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview6 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@jozkee backporting to release/11.0-preview6 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: First API proposal implementationUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/ref/System.Memory.csM	src/libraries/System.Memory/tests/System.Memory.Tests.csprojM	src/libraries/System.Private.CoreLib/src/Resources/Strings.resxM	src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsM	src/libraries/System.Runtime/ref/System.Runtime.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/ref/System.Memory.csAuto-merging src/libraries/System.Memory/tests/System.Memory.Tests.csprojAuto-merging src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAuto-merging src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsAuto-merging src/libraries/System.Runtime/ref/System.Runtime.csApplying: API replacements in production codeApplying: Implementation update based on latest API Review final consensusApplying: Address PR feedback. MemoryStream base change. Spillover buffer for Convert edge case. Flush strategy update.Applying: Address PR feedbackApplying: Address PR feedback: fix StringStream flush offset, WritableMemoryStream length/seek semantics, ReadOnlySequenceStream safety, and consolidate testsApplying: Address PR feedback: remove redundant code, improve test coverage and structureUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csM	src/libraries/System.Net.Http/src/System.Net.Http.csprojM	src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csM	src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csM	src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csAuto-merging src/libraries/System.Net.Http/src/System.Net.Http.csprojAuto-merging src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csAuto-merging src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csCONFLICT (content): Merge conflict in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0007 Address PR feedback: remove redundant code, improve test coverage and structureError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

jozkee pushed a commit that referenced this pull request Jun 25, 2026
… types (#129811)
Backport of #126669 to
release/11.0-preview6. See that PR for full details.
Adds new public stream wrapper APIs (`StringStream`,
`ReadOnlyMemoryStream`, `WritableMemoryStream`,
`ReadOnlySequenceStream`).
Fixes#82801.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 25, 2026
SimonCropp added a commit to SimonCropp/Polyfill 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
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Fixes#82801
Introduces standardized stream wrappers for text and memory types as
public sealed classes (`StringStream`, `ReadOnlyMemoryStream`,
`WritableMemoryStream`, and `ReadOnlySequenceStream` ) as approved in
[API
review](#82801 (comment))
([video](https://www.youtube.com/watch?v=T7xc7rARCEw&t=0h9m41s)).
### What's included
- `StringStream` (`System.IO`, CoreLib): non-seekable, read-only stream
that encodes `string` or `ReadOnlyMemory<char>` on-the-fly. Encoding is
required (no default). Never emits BOMs.
- `ReadOnlyMemoryStream` (`System.IO`, CoreLib): seekable, read-only
stream over `ReadOnlyMemory<byte>`
- `WritableMemoryStream` (`System.IO`, CoreLib): seekable, read-write
stream over `Memory<byte>` with fixed capacity
- `ReadOnlySequenceStream` (`System.Buffers`, System.Memory): seekable,
read-only stream over `ReadOnlySequence<byte>`
- Ref assembly updates for `System.Runtime` and `System.Memory`
- Updated 3 internal call sites (`ReadOnlyMemoryContent`,
`XmlPreloadedResolver`, `JsonXmlDataContract`) to use the new types
- Conformance and behavioral tests for all 4 types
### Implementation notes
- All types are `public sealed` with direct constructors: the review
moved away from factory methods on `Stream` to avoid derived-type
IntelliSense noise
- `StringStream` encodes directly into the caller's buffer in `Read()`
rather than using an internal byte buffer
- `ReadOnlyMemoryStream` and `WritableMemoryStream` derive from
`MemoryStream`.
- `TryGetBuffer` returns false and `GetBuffer` throws on the memory
stream types (no `publiclyVisible` support for now)
### Limitations
- The internal
[shared-source](https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/ReadOnlyMemoryStream.cs)
`ReadOnlyMemoryStream` in `Common/` cannot be fully replaced:
- `System.Memory.Data` multi-targets `netstandard2.0` where the new
public type doesn't exist.
- `System.Net.Http` (net11.0 only) can adopt it directly.
### Follow-up work
- `IBufferWriter<byte>` → `Stream` wrapper (separate proposal per
[#100434](#100434))
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add Stream wrappers for memory and text-based types

8 participants

@ViveliDuCh@SimonCropp@jozkee@stephentoub@adamsitnik@bartonjs@tarekgh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add Stream wrappers for memory and text-based types - #126669

Merged
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api
Jun 24, 2026
Merged

Add Stream wrappers for memory and text-based types#126669
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api

Conversation

@ViveliDuCh

@ViveliDuChViveliDuCh commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fixes#82801

Introduces standardized stream wrappers for text and memory types as public sealed classes (StringStream, ReadOnlyMemoryStream, WritableMemoryStream, and ReadOnlySequenceStream ) as approved in API review (video).

What's included

  • StringStream (System.IO, CoreLib): non-seekable, read-only stream that encodes string or ReadOnlyMemory<char> on-the-fly. Encoding is required (no default). Never emits BOMs.
  • ReadOnlyMemoryStream (System.IO, CoreLib): seekable, read-only stream over ReadOnlyMemory<byte>
  • WritableMemoryStream (System.IO, CoreLib): seekable, read-write stream over Memory<byte> with fixed capacity
  • ReadOnlySequenceStream (System.Buffers, System.Memory): seekable, read-only stream over ReadOnlySequence<byte>
  • Ref assembly updates for System.Runtime and System.Memory
  • Updated 3 internal call sites (ReadOnlyMemoryContent, XmlPreloadedResolver, JsonXmlDataContract) to use the new types
  • Conformance and behavioral tests for all 4 types

Implementation notes

  • All types are public sealed with direct constructors: the review moved away from factory methods on Stream to avoid derived-type IntelliSense noise
  • StringStream encodes directly into the caller's buffer in Read() rather than using an internal byte buffer
  • ReadOnlyMemoryStream and WritableMemoryStream derive from MemoryStream.
  • TryGetBuffer returns false and GetBuffer throws on the memory stream types (no publiclyVisible support for now)

Limitations

  • The internal shared-sourceReadOnlyMemoryStream in Common/ cannot be fully replaced:
    • System.Memory.Data multi-targets netstandard2.0 where the new public type doesn't exist.
    • System.Net.Http (net11.0 only) can adopt it directly.

Follow-up work

  • IBufferWriter<byte>Stream wrapper (separate proposal per #100434)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces new standardized Stream wrapper types across CoreLib and System.Memory, aligning with the approved API shape from #82801 and updating a few internal call sites to use the new wrappers.

Changes:

  • Added new public sealed stream wrappers: StringStream, ReadOnlyMemoryStream, WritableMemoryStream (CoreLib) and ReadOnlySequenceStream (System.Memory).
  • Updated reference assemblies and project files to expose/compile the new APIs.
  • Added conformance + targeted behavioral tests, and updated select internal consumers to use StringStream.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/IO/StringStream.csImplements the new StringStream API (read-only, non-seekable, on-the-fly encoding).
src/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.csImplements seekable read-only stream over ReadOnlyMemory<byte>.
src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csImplements seekable fixed-capacity read/write stream over Memory<byte>.
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsWires new CoreLib stream wrapper source files into the build.
src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAdds a new resource string entry (currently appears unused).
src/libraries/System.Runtime/ref/System.Runtime.csUpdates public API surface to include the new stream wrapper types (and a small ref signature normalization change).
src/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csprojIncludes the new test files in the System.IO test project.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamConformanceTests.csAdds conformance coverage for StringStream (string + ReadOnlyMemory<char> overloads).
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAdds targeted StringStream(string, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAdds targeted StringStream(ReadOnlyMemory<char>, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAdds conformance coverage for ReadOnlyMemoryStream.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamTests.csAdds targeted ReadOnlyMemoryStream behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAdds conformance coverage for WritableMemoryStream (with some overridden tests).
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csAdds targeted WritableMemoryStream behavioral tests.
src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csImplements ReadOnlySequenceStream over ReadOnlySequence<byte>.
src/libraries/System.Memory/src/System.Memory.csprojIncludes the new ReadOnlySequenceStream source file in System.Memory.
src/libraries/System.Memory/src/Resources/Strings.resxAdds SR strings needed for stream-like exception messages in System.Memory.
src/libraries/System.Memory/ref/System.Memory.csAdds ReadOnlySequenceStream to the System.Memory ref surface.
src/libraries/System.Memory/tests/System.Memory.Tests.csprojAdds tests for ReadOnlySequenceStream and references StreamConformanceTests.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStreamTests.csAdds targeted behavioral tests for multi-segment ReadOnlySequenceStream scenarios.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStream.ConformanceTests.csAdds conformance coverage for ReadOnlySequenceStream.
src/libraries/System.Private.Xml/src/System/Xml/Resolvers/XmlPreloadedResolver.csSwitches internal string-to-stream conversion to StringStream.
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csSwitches internal string-to-stream conversion to StringStream.
Comments suppressed due to low confidence (1)

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.cs:38

  • Variable is still named 'memoryStream' but the implementation is now StringStream (not a MemoryStream). Rename the local to avoid implying the stream is seekable/in-memory-buffered (e.g., 'xmlContentStream').
 Stream memoryStream = new StringStream(xmlContent, Encoding.UTF8);
object? xmlValue;
XmlDictionaryReaderQuotas? quotas = ((JsonReaderDelegator)jsonReader).ReaderQuotas;
if (quotas == null)
{
xmlValue = dataContractSerializer.ReadObject(memoryStream);

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/ref/System.Runtime.cs
Comment threadsrc/libraries/System.Private.CoreLib/src/Resources/Strings.resx Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Memory/ref/System.Memory.cs
CopilotAI review requested due to automatic review settings April 9, 2026 08:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csproj Outdated
Comment threadsrc/libraries/System.Memory/src/System.Memory.csproj Outdated
Comment threadsrc/libraries/System.Memory/tests/System.Memory.Tests.csproj Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings April 13, 2026 19:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings June 23, 2026 23:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@SimonCropp

Copy link
Copy Markdown
Contributor

awesome. that .net preview will this be in?

SimonCropp added a commit to SimonCropp/Polyfill that referenced this pull request Jun 24, 2026
* Add Stream wrappers for memory and text-based types
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.
* .
@jozkee

Copy link
Copy Markdown
Member

/backport to release/11.0-preview6

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview6 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@jozkee backporting to release/11.0-preview6 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: First API proposal implementationUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/ref/System.Memory.csM	src/libraries/System.Memory/tests/System.Memory.Tests.csprojM	src/libraries/System.Private.CoreLib/src/Resources/Strings.resxM	src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsM	src/libraries/System.Runtime/ref/System.Runtime.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/ref/System.Memory.csAuto-merging src/libraries/System.Memory/tests/System.Memory.Tests.csprojAuto-merging src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAuto-merging src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsAuto-merging src/libraries/System.Runtime/ref/System.Runtime.csApplying: API replacements in production codeApplying: Implementation update based on latest API Review final consensusApplying: Address PR feedback. MemoryStream base change. Spillover buffer for Convert edge case. Flush strategy update.Applying: Address PR feedbackApplying: Address PR feedback: fix StringStream flush offset, WritableMemoryStream length/seek semantics, ReadOnlySequenceStream safety, and consolidate testsApplying: Address PR feedback: remove redundant code, improve test coverage and structureUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csM	src/libraries/System.Net.Http/src/System.Net.Http.csprojM	src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csM	src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csM	src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csAuto-merging src/libraries/System.Net.Http/src/System.Net.Http.csprojAuto-merging src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csAuto-merging src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csCONFLICT (content): Merge conflict in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0007 Address PR feedback: remove redundant code, improve test coverage and structureError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

jozkee pushed a commit that referenced this pull request Jun 25, 2026
… types (#129811)
Backport of #126669 to
release/11.0-preview6. See that PR for full details.
Adds new public stream wrapper APIs (`StringStream`,
`ReadOnlyMemoryStream`, `WritableMemoryStream`,
`ReadOnlySequenceStream`).
Fixes#82801.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 25, 2026
SimonCropp added a commit to SimonCropp/Polyfill 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
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Fixes#82801
Introduces standardized stream wrappers for text and memory types as
public sealed classes (`StringStream`, `ReadOnlyMemoryStream`,
`WritableMemoryStream`, and `ReadOnlySequenceStream` ) as approved in
[API
review](#82801 (comment))
([video](https://www.youtube.com/watch?v=T7xc7rARCEw&t=0h9m41s)).
### What's included
- `StringStream` (`System.IO`, CoreLib): non-seekable, read-only stream
that encodes `string` or `ReadOnlyMemory<char>` on-the-fly. Encoding is
required (no default). Never emits BOMs.
- `ReadOnlyMemoryStream` (`System.IO`, CoreLib): seekable, read-only
stream over `ReadOnlyMemory<byte>`
- `WritableMemoryStream` (`System.IO`, CoreLib): seekable, read-write
stream over `Memory<byte>` with fixed capacity
- `ReadOnlySequenceStream` (`System.Buffers`, System.Memory): seekable,
read-only stream over `ReadOnlySequence<byte>`
- Ref assembly updates for `System.Runtime` and `System.Memory`
- Updated 3 internal call sites (`ReadOnlyMemoryContent`,
`XmlPreloadedResolver`, `JsonXmlDataContract`) to use the new types
- Conformance and behavioral tests for all 4 types
### Implementation notes
- All types are `public sealed` with direct constructors: the review
moved away from factory methods on `Stream` to avoid derived-type
IntelliSense noise
- `StringStream` encodes directly into the caller's buffer in `Read()`
rather than using an internal byte buffer
- `ReadOnlyMemoryStream` and `WritableMemoryStream` derive from
`MemoryStream`.
- `TryGetBuffer` returns false and `GetBuffer` throws on the memory
stream types (no `publiclyVisible` support for now)
### Limitations
- The internal
[shared-source](https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/ReadOnlyMemoryStream.cs)
`ReadOnlyMemoryStream` in `Common/` cannot be fully replaced:
- `System.Memory.Data` multi-targets `netstandard2.0` where the new
public type doesn't exist.
- `System.Net.Http` (net11.0 only) can adopt it directly.
### Follow-up work
- `IBufferWriter<byte>` → `Stream` wrapper (separate proposal per
[#100434](#100434))
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add Stream wrappers for memory and text-based types

8 participants

@ViveliDuCh@SimonCropp@jozkee@stephentoub@adamsitnik@bartonjs@tarekgh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add Stream wrappers for memory and text-based types - #126669

Merged
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api
Jun 24, 2026
Merged

Add Stream wrappers for memory and text-based types#126669
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api

Conversation

@ViveliDuCh

@ViveliDuChViveliDuCh commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fixes#82801

Introduces standardized stream wrappers for text and memory types as public sealed classes (StringStream, ReadOnlyMemoryStream, WritableMemoryStream, and ReadOnlySequenceStream ) as approved in API review (video).

What's included

  • StringStream (System.IO, CoreLib): non-seekable, read-only stream that encodes string or ReadOnlyMemory<char> on-the-fly. Encoding is required (no default). Never emits BOMs.
  • ReadOnlyMemoryStream (System.IO, CoreLib): seekable, read-only stream over ReadOnlyMemory<byte>
  • WritableMemoryStream (System.IO, CoreLib): seekable, read-write stream over Memory<byte> with fixed capacity
  • ReadOnlySequenceStream (System.Buffers, System.Memory): seekable, read-only stream over ReadOnlySequence<byte>
  • Ref assembly updates for System.Runtime and System.Memory
  • Updated 3 internal call sites (ReadOnlyMemoryContent, XmlPreloadedResolver, JsonXmlDataContract) to use the new types
  • Conformance and behavioral tests for all 4 types

Implementation notes

  • All types are public sealed with direct constructors: the review moved away from factory methods on Stream to avoid derived-type IntelliSense noise
  • StringStream encodes directly into the caller's buffer in Read() rather than using an internal byte buffer
  • ReadOnlyMemoryStream and WritableMemoryStream derive from MemoryStream.
  • TryGetBuffer returns false and GetBuffer throws on the memory stream types (no publiclyVisible support for now)

Limitations

  • The internal shared-sourceReadOnlyMemoryStream in Common/ cannot be fully replaced:
    • System.Memory.Data multi-targets netstandard2.0 where the new public type doesn't exist.
    • System.Net.Http (net11.0 only) can adopt it directly.

Follow-up work

  • IBufferWriter<byte>Stream wrapper (separate proposal per #100434)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces new standardized Stream wrapper types across CoreLib and System.Memory, aligning with the approved API shape from #82801 and updating a few internal call sites to use the new wrappers.

Changes:

  • Added new public sealed stream wrappers: StringStream, ReadOnlyMemoryStream, WritableMemoryStream (CoreLib) and ReadOnlySequenceStream (System.Memory).
  • Updated reference assemblies and project files to expose/compile the new APIs.
  • Added conformance + targeted behavioral tests, and updated select internal consumers to use StringStream.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/IO/StringStream.csImplements the new StringStream API (read-only, non-seekable, on-the-fly encoding).
src/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.csImplements seekable read-only stream over ReadOnlyMemory<byte>.
src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csImplements seekable fixed-capacity read/write stream over Memory<byte>.
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsWires new CoreLib stream wrapper source files into the build.
src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAdds a new resource string entry (currently appears unused).
src/libraries/System.Runtime/ref/System.Runtime.csUpdates public API surface to include the new stream wrapper types (and a small ref signature normalization change).
src/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csprojIncludes the new test files in the System.IO test project.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamConformanceTests.csAdds conformance coverage for StringStream (string + ReadOnlyMemory<char> overloads).
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAdds targeted StringStream(string, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAdds targeted StringStream(ReadOnlyMemory<char>, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAdds conformance coverage for ReadOnlyMemoryStream.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamTests.csAdds targeted ReadOnlyMemoryStream behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAdds conformance coverage for WritableMemoryStream (with some overridden tests).
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csAdds targeted WritableMemoryStream behavioral tests.
src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csImplements ReadOnlySequenceStream over ReadOnlySequence<byte>.
src/libraries/System.Memory/src/System.Memory.csprojIncludes the new ReadOnlySequenceStream source file in System.Memory.
src/libraries/System.Memory/src/Resources/Strings.resxAdds SR strings needed for stream-like exception messages in System.Memory.
src/libraries/System.Memory/ref/System.Memory.csAdds ReadOnlySequenceStream to the System.Memory ref surface.
src/libraries/System.Memory/tests/System.Memory.Tests.csprojAdds tests for ReadOnlySequenceStream and references StreamConformanceTests.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStreamTests.csAdds targeted behavioral tests for multi-segment ReadOnlySequenceStream scenarios.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStream.ConformanceTests.csAdds conformance coverage for ReadOnlySequenceStream.
src/libraries/System.Private.Xml/src/System/Xml/Resolvers/XmlPreloadedResolver.csSwitches internal string-to-stream conversion to StringStream.
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csSwitches internal string-to-stream conversion to StringStream.
Comments suppressed due to low confidence (1)

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.cs:38

  • Variable is still named 'memoryStream' but the implementation is now StringStream (not a MemoryStream). Rename the local to avoid implying the stream is seekable/in-memory-buffered (e.g., 'xmlContentStream').
 Stream memoryStream = new StringStream(xmlContent, Encoding.UTF8);
object? xmlValue;
XmlDictionaryReaderQuotas? quotas = ((JsonReaderDelegator)jsonReader).ReaderQuotas;
if (quotas == null)
{
xmlValue = dataContractSerializer.ReadObject(memoryStream);

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/ref/System.Runtime.cs
Comment threadsrc/libraries/System.Private.CoreLib/src/Resources/Strings.resx Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Memory/ref/System.Memory.cs
CopilotAI review requested due to automatic review settings April 9, 2026 08:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csproj Outdated
Comment threadsrc/libraries/System.Memory/src/System.Memory.csproj Outdated
Comment threadsrc/libraries/System.Memory/tests/System.Memory.Tests.csproj Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings April 13, 2026 19:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings June 23, 2026 23:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@SimonCropp

Copy link
Copy Markdown
Contributor

awesome. that .net preview will this be in?

SimonCropp added a commit to SimonCropp/Polyfill that referenced this pull request Jun 24, 2026
* Add Stream wrappers for memory and text-based types
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.
* .
@jozkee

Copy link
Copy Markdown
Member

/backport to release/11.0-preview6

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview6 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@jozkee backporting to release/11.0-preview6 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: First API proposal implementationUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/ref/System.Memory.csM	src/libraries/System.Memory/tests/System.Memory.Tests.csprojM	src/libraries/System.Private.CoreLib/src/Resources/Strings.resxM	src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsM	src/libraries/System.Runtime/ref/System.Runtime.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/ref/System.Memory.csAuto-merging src/libraries/System.Memory/tests/System.Memory.Tests.csprojAuto-merging src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAuto-merging src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsAuto-merging src/libraries/System.Runtime/ref/System.Runtime.csApplying: API replacements in production codeApplying: Implementation update based on latest API Review final consensusApplying: Address PR feedback. MemoryStream base change. Spillover buffer for Convert edge case. Flush strategy update.Applying: Address PR feedbackApplying: Address PR feedback: fix StringStream flush offset, WritableMemoryStream length/seek semantics, ReadOnlySequenceStream safety, and consolidate testsApplying: Address PR feedback: remove redundant code, improve test coverage and structureUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csM	src/libraries/System.Net.Http/src/System.Net.Http.csprojM	src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csM	src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csM	src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csAuto-merging src/libraries/System.Net.Http/src/System.Net.Http.csprojAuto-merging src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csAuto-merging src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csCONFLICT (content): Merge conflict in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0007 Address PR feedback: remove redundant code, improve test coverage and structureError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

jozkee pushed a commit that referenced this pull request Jun 25, 2026
… types (#129811)
Backport of #126669 to
release/11.0-preview6. See that PR for full details.
Adds new public stream wrapper APIs (`StringStream`,
`ReadOnlyMemoryStream`, `WritableMemoryStream`,
`ReadOnlySequenceStream`).
Fixes#82801.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 25, 2026
SimonCropp added a commit to SimonCropp/Polyfill 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
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Fixes#82801
Introduces standardized stream wrappers for text and memory types as
public sealed classes (`StringStream`, `ReadOnlyMemoryStream`,
`WritableMemoryStream`, and `ReadOnlySequenceStream` ) as approved in
[API
review](#82801 (comment))
([video](https://www.youtube.com/watch?v=T7xc7rARCEw&t=0h9m41s)).
### What's included
- `StringStream` (`System.IO`, CoreLib): non-seekable, read-only stream
that encodes `string` or `ReadOnlyMemory<char>` on-the-fly. Encoding is
required (no default). Never emits BOMs.
- `ReadOnlyMemoryStream` (`System.IO`, CoreLib): seekable, read-only
stream over `ReadOnlyMemory<byte>`
- `WritableMemoryStream` (`System.IO`, CoreLib): seekable, read-write
stream over `Memory<byte>` with fixed capacity
- `ReadOnlySequenceStream` (`System.Buffers`, System.Memory): seekable,
read-only stream over `ReadOnlySequence<byte>`
- Ref assembly updates for `System.Runtime` and `System.Memory`
- Updated 3 internal call sites (`ReadOnlyMemoryContent`,
`XmlPreloadedResolver`, `JsonXmlDataContract`) to use the new types
- Conformance and behavioral tests for all 4 types
### Implementation notes
- All types are `public sealed` with direct constructors: the review
moved away from factory methods on `Stream` to avoid derived-type
IntelliSense noise
- `StringStream` encodes directly into the caller's buffer in `Read()`
rather than using an internal byte buffer
- `ReadOnlyMemoryStream` and `WritableMemoryStream` derive from
`MemoryStream`.
- `TryGetBuffer` returns false and `GetBuffer` throws on the memory
stream types (no `publiclyVisible` support for now)
### Limitations
- The internal
[shared-source](https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/ReadOnlyMemoryStream.cs)
`ReadOnlyMemoryStream` in `Common/` cannot be fully replaced:
- `System.Memory.Data` multi-targets `netstandard2.0` where the new
public type doesn't exist.
- `System.Net.Http` (net11.0 only) can adopt it directly.
### Follow-up work
- `IBufferWriter<byte>` → `Stream` wrapper (separate proposal per
[#100434](#100434))
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add Stream wrappers for memory and text-based types

8 participants

@ViveliDuCh@SimonCropp@jozkee@stephentoub@adamsitnik@bartonjs@tarekgh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add Stream wrappers for memory and text-based types - #126669

Merged
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api
Jun 24, 2026
Merged

Add Stream wrappers for memory and text-based types#126669
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api

Conversation

@ViveliDuCh

@ViveliDuChViveliDuCh commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fixes#82801

Introduces standardized stream wrappers for text and memory types as public sealed classes (StringStream, ReadOnlyMemoryStream, WritableMemoryStream, and ReadOnlySequenceStream ) as approved in API review (video).

What's included

  • StringStream (System.IO, CoreLib): non-seekable, read-only stream that encodes string or ReadOnlyMemory<char> on-the-fly. Encoding is required (no default). Never emits BOMs.
  • ReadOnlyMemoryStream (System.IO, CoreLib): seekable, read-only stream over ReadOnlyMemory<byte>
  • WritableMemoryStream (System.IO, CoreLib): seekable, read-write stream over Memory<byte> with fixed capacity
  • ReadOnlySequenceStream (System.Buffers, System.Memory): seekable, read-only stream over ReadOnlySequence<byte>
  • Ref assembly updates for System.Runtime and System.Memory
  • Updated 3 internal call sites (ReadOnlyMemoryContent, XmlPreloadedResolver, JsonXmlDataContract) to use the new types
  • Conformance and behavioral tests for all 4 types

Implementation notes

  • All types are public sealed with direct constructors: the review moved away from factory methods on Stream to avoid derived-type IntelliSense noise
  • StringStream encodes directly into the caller's buffer in Read() rather than using an internal byte buffer
  • ReadOnlyMemoryStream and WritableMemoryStream derive from MemoryStream.
  • TryGetBuffer returns false and GetBuffer throws on the memory stream types (no publiclyVisible support for now)

Limitations

  • The internal shared-sourceReadOnlyMemoryStream in Common/ cannot be fully replaced:
    • System.Memory.Data multi-targets netstandard2.0 where the new public type doesn't exist.
    • System.Net.Http (net11.0 only) can adopt it directly.

Follow-up work

  • IBufferWriter<byte>Stream wrapper (separate proposal per #100434)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces new standardized Stream wrapper types across CoreLib and System.Memory, aligning with the approved API shape from #82801 and updating a few internal call sites to use the new wrappers.

Changes:

  • Added new public sealed stream wrappers: StringStream, ReadOnlyMemoryStream, WritableMemoryStream (CoreLib) and ReadOnlySequenceStream (System.Memory).
  • Updated reference assemblies and project files to expose/compile the new APIs.
  • Added conformance + targeted behavioral tests, and updated select internal consumers to use StringStream.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/IO/StringStream.csImplements the new StringStream API (read-only, non-seekable, on-the-fly encoding).
src/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.csImplements seekable read-only stream over ReadOnlyMemory<byte>.
src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csImplements seekable fixed-capacity read/write stream over Memory<byte>.
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsWires new CoreLib stream wrapper source files into the build.
src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAdds a new resource string entry (currently appears unused).
src/libraries/System.Runtime/ref/System.Runtime.csUpdates public API surface to include the new stream wrapper types (and a small ref signature normalization change).
src/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csprojIncludes the new test files in the System.IO test project.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamConformanceTests.csAdds conformance coverage for StringStream (string + ReadOnlyMemory<char> overloads).
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAdds targeted StringStream(string, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAdds targeted StringStream(ReadOnlyMemory<char>, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAdds conformance coverage for ReadOnlyMemoryStream.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamTests.csAdds targeted ReadOnlyMemoryStream behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAdds conformance coverage for WritableMemoryStream (with some overridden tests).
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csAdds targeted WritableMemoryStream behavioral tests.
src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csImplements ReadOnlySequenceStream over ReadOnlySequence<byte>.
src/libraries/System.Memory/src/System.Memory.csprojIncludes the new ReadOnlySequenceStream source file in System.Memory.
src/libraries/System.Memory/src/Resources/Strings.resxAdds SR strings needed for stream-like exception messages in System.Memory.
src/libraries/System.Memory/ref/System.Memory.csAdds ReadOnlySequenceStream to the System.Memory ref surface.
src/libraries/System.Memory/tests/System.Memory.Tests.csprojAdds tests for ReadOnlySequenceStream and references StreamConformanceTests.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStreamTests.csAdds targeted behavioral tests for multi-segment ReadOnlySequenceStream scenarios.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStream.ConformanceTests.csAdds conformance coverage for ReadOnlySequenceStream.
src/libraries/System.Private.Xml/src/System/Xml/Resolvers/XmlPreloadedResolver.csSwitches internal string-to-stream conversion to StringStream.
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csSwitches internal string-to-stream conversion to StringStream.
Comments suppressed due to low confidence (1)

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.cs:38

  • Variable is still named 'memoryStream' but the implementation is now StringStream (not a MemoryStream). Rename the local to avoid implying the stream is seekable/in-memory-buffered (e.g., 'xmlContentStream').
 Stream memoryStream = new StringStream(xmlContent, Encoding.UTF8);
object? xmlValue;
XmlDictionaryReaderQuotas? quotas = ((JsonReaderDelegator)jsonReader).ReaderQuotas;
if (quotas == null)
{
xmlValue = dataContractSerializer.ReadObject(memoryStream);

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/ref/System.Runtime.cs
Comment threadsrc/libraries/System.Private.CoreLib/src/Resources/Strings.resx Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Memory/ref/System.Memory.cs
CopilotAI review requested due to automatic review settings April 9, 2026 08:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csproj Outdated
Comment threadsrc/libraries/System.Memory/src/System.Memory.csproj Outdated
Comment threadsrc/libraries/System.Memory/tests/System.Memory.Tests.csproj Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings April 13, 2026 19:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings June 23, 2026 23:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@SimonCropp

Copy link
Copy Markdown
Contributor

awesome. that .net preview will this be in?

SimonCropp added a commit to SimonCropp/Polyfill that referenced this pull request Jun 24, 2026
* Add Stream wrappers for memory and text-based types
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.
* .
@jozkee

Copy link
Copy Markdown
Member

/backport to release/11.0-preview6

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview6 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@jozkee backporting to release/11.0-preview6 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: First API proposal implementationUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/ref/System.Memory.csM	src/libraries/System.Memory/tests/System.Memory.Tests.csprojM	src/libraries/System.Private.CoreLib/src/Resources/Strings.resxM	src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsM	src/libraries/System.Runtime/ref/System.Runtime.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/ref/System.Memory.csAuto-merging src/libraries/System.Memory/tests/System.Memory.Tests.csprojAuto-merging src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAuto-merging src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsAuto-merging src/libraries/System.Runtime/ref/System.Runtime.csApplying: API replacements in production codeApplying: Implementation update based on latest API Review final consensusApplying: Address PR feedback. MemoryStream base change. Spillover buffer for Convert edge case. Flush strategy update.Applying: Address PR feedbackApplying: Address PR feedback: fix StringStream flush offset, WritableMemoryStream length/seek semantics, ReadOnlySequenceStream safety, and consolidate testsApplying: Address PR feedback: remove redundant code, improve test coverage and structureUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csM	src/libraries/System.Net.Http/src/System.Net.Http.csprojM	src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csM	src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csM	src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csAuto-merging src/libraries/System.Net.Http/src/System.Net.Http.csprojAuto-merging src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csAuto-merging src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csCONFLICT (content): Merge conflict in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0007 Address PR feedback: remove redundant code, improve test coverage and structureError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

jozkee pushed a commit that referenced this pull request Jun 25, 2026
… types (#129811)
Backport of #126669 to
release/11.0-preview6. See that PR for full details.
Adds new public stream wrapper APIs (`StringStream`,
`ReadOnlyMemoryStream`, `WritableMemoryStream`,
`ReadOnlySequenceStream`).
Fixes#82801.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 25, 2026
SimonCropp added a commit to SimonCropp/Polyfill 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
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Fixes#82801
Introduces standardized stream wrappers for text and memory types as
public sealed classes (`StringStream`, `ReadOnlyMemoryStream`,
`WritableMemoryStream`, and `ReadOnlySequenceStream` ) as approved in
[API
review](#82801 (comment))
([video](https://www.youtube.com/watch?v=T7xc7rARCEw&t=0h9m41s)).
### What's included
- `StringStream` (`System.IO`, CoreLib): non-seekable, read-only stream
that encodes `string` or `ReadOnlyMemory<char>` on-the-fly. Encoding is
required (no default). Never emits BOMs.
- `ReadOnlyMemoryStream` (`System.IO`, CoreLib): seekable, read-only
stream over `ReadOnlyMemory<byte>`
- `WritableMemoryStream` (`System.IO`, CoreLib): seekable, read-write
stream over `Memory<byte>` with fixed capacity
- `ReadOnlySequenceStream` (`System.Buffers`, System.Memory): seekable,
read-only stream over `ReadOnlySequence<byte>`
- Ref assembly updates for `System.Runtime` and `System.Memory`
- Updated 3 internal call sites (`ReadOnlyMemoryContent`,
`XmlPreloadedResolver`, `JsonXmlDataContract`) to use the new types
- Conformance and behavioral tests for all 4 types
### Implementation notes
- All types are `public sealed` with direct constructors: the review
moved away from factory methods on `Stream` to avoid derived-type
IntelliSense noise
- `StringStream` encodes directly into the caller's buffer in `Read()`
rather than using an internal byte buffer
- `ReadOnlyMemoryStream` and `WritableMemoryStream` derive from
`MemoryStream`.
- `TryGetBuffer` returns false and `GetBuffer` throws on the memory
stream types (no `publiclyVisible` support for now)
### Limitations
- The internal
[shared-source](https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/ReadOnlyMemoryStream.cs)
`ReadOnlyMemoryStream` in `Common/` cannot be fully replaced:
- `System.Memory.Data` multi-targets `netstandard2.0` where the new
public type doesn't exist.
- `System.Net.Http` (net11.0 only) can adopt it directly.
### Follow-up work
- `IBufferWriter<byte>` → `Stream` wrapper (separate proposal per
[#100434](#100434))
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add Stream wrappers for memory and text-based types

8 participants

@ViveliDuCh@SimonCropp@jozkee@stephentoub@adamsitnik@bartonjs@tarekgh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add Stream wrappers for memory and text-based types - #126669

Merged
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api
Jun 24, 2026
Merged

Add Stream wrappers for memory and text-based types#126669
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api

Conversation

@ViveliDuCh

@ViveliDuChViveliDuCh commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fixes#82801

Introduces standardized stream wrappers for text and memory types as public sealed classes (StringStream, ReadOnlyMemoryStream, WritableMemoryStream, and ReadOnlySequenceStream ) as approved in API review (video).

What's included

  • StringStream (System.IO, CoreLib): non-seekable, read-only stream that encodes string or ReadOnlyMemory<char> on-the-fly. Encoding is required (no default). Never emits BOMs.
  • ReadOnlyMemoryStream (System.IO, CoreLib): seekable, read-only stream over ReadOnlyMemory<byte>
  • WritableMemoryStream (System.IO, CoreLib): seekable, read-write stream over Memory<byte> with fixed capacity
  • ReadOnlySequenceStream (System.Buffers, System.Memory): seekable, read-only stream over ReadOnlySequence<byte>
  • Ref assembly updates for System.Runtime and System.Memory
  • Updated 3 internal call sites (ReadOnlyMemoryContent, XmlPreloadedResolver, JsonXmlDataContract) to use the new types
  • Conformance and behavioral tests for all 4 types

Implementation notes

  • All types are public sealed with direct constructors: the review moved away from factory methods on Stream to avoid derived-type IntelliSense noise
  • StringStream encodes directly into the caller's buffer in Read() rather than using an internal byte buffer
  • ReadOnlyMemoryStream and WritableMemoryStream derive from MemoryStream.
  • TryGetBuffer returns false and GetBuffer throws on the memory stream types (no publiclyVisible support for now)

Limitations

  • The internal shared-sourceReadOnlyMemoryStream in Common/ cannot be fully replaced:
    • System.Memory.Data multi-targets netstandard2.0 where the new public type doesn't exist.
    • System.Net.Http (net11.0 only) can adopt it directly.

Follow-up work

  • IBufferWriter<byte>Stream wrapper (separate proposal per #100434)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces new standardized Stream wrapper types across CoreLib and System.Memory, aligning with the approved API shape from #82801 and updating a few internal call sites to use the new wrappers.

Changes:

  • Added new public sealed stream wrappers: StringStream, ReadOnlyMemoryStream, WritableMemoryStream (CoreLib) and ReadOnlySequenceStream (System.Memory).
  • Updated reference assemblies and project files to expose/compile the new APIs.
  • Added conformance + targeted behavioral tests, and updated select internal consumers to use StringStream.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/IO/StringStream.csImplements the new StringStream API (read-only, non-seekable, on-the-fly encoding).
src/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.csImplements seekable read-only stream over ReadOnlyMemory<byte>.
src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csImplements seekable fixed-capacity read/write stream over Memory<byte>.
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsWires new CoreLib stream wrapper source files into the build.
src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAdds a new resource string entry (currently appears unused).
src/libraries/System.Runtime/ref/System.Runtime.csUpdates public API surface to include the new stream wrapper types (and a small ref signature normalization change).
src/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csprojIncludes the new test files in the System.IO test project.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamConformanceTests.csAdds conformance coverage for StringStream (string + ReadOnlyMemory<char> overloads).
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAdds targeted StringStream(string, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAdds targeted StringStream(ReadOnlyMemory<char>, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAdds conformance coverage for ReadOnlyMemoryStream.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamTests.csAdds targeted ReadOnlyMemoryStream behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAdds conformance coverage for WritableMemoryStream (with some overridden tests).
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csAdds targeted WritableMemoryStream behavioral tests.
src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csImplements ReadOnlySequenceStream over ReadOnlySequence<byte>.
src/libraries/System.Memory/src/System.Memory.csprojIncludes the new ReadOnlySequenceStream source file in System.Memory.
src/libraries/System.Memory/src/Resources/Strings.resxAdds SR strings needed for stream-like exception messages in System.Memory.
src/libraries/System.Memory/ref/System.Memory.csAdds ReadOnlySequenceStream to the System.Memory ref surface.
src/libraries/System.Memory/tests/System.Memory.Tests.csprojAdds tests for ReadOnlySequenceStream and references StreamConformanceTests.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStreamTests.csAdds targeted behavioral tests for multi-segment ReadOnlySequenceStream scenarios.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStream.ConformanceTests.csAdds conformance coverage for ReadOnlySequenceStream.
src/libraries/System.Private.Xml/src/System/Xml/Resolvers/XmlPreloadedResolver.csSwitches internal string-to-stream conversion to StringStream.
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csSwitches internal string-to-stream conversion to StringStream.
Comments suppressed due to low confidence (1)

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.cs:38

  • Variable is still named 'memoryStream' but the implementation is now StringStream (not a MemoryStream). Rename the local to avoid implying the stream is seekable/in-memory-buffered (e.g., 'xmlContentStream').
 Stream memoryStream = new StringStream(xmlContent, Encoding.UTF8);
object? xmlValue;
XmlDictionaryReaderQuotas? quotas = ((JsonReaderDelegator)jsonReader).ReaderQuotas;
if (quotas == null)
{
xmlValue = dataContractSerializer.ReadObject(memoryStream);

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/ref/System.Runtime.cs
Comment threadsrc/libraries/System.Private.CoreLib/src/Resources/Strings.resx Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Memory/ref/System.Memory.cs
CopilotAI review requested due to automatic review settings April 9, 2026 08:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csproj Outdated
Comment threadsrc/libraries/System.Memory/src/System.Memory.csproj Outdated
Comment threadsrc/libraries/System.Memory/tests/System.Memory.Tests.csproj Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings April 13, 2026 19:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings June 23, 2026 23:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@SimonCropp

Copy link
Copy Markdown
Contributor

awesome. that .net preview will this be in?

SimonCropp added a commit to SimonCropp/Polyfill that referenced this pull request Jun 24, 2026
* Add Stream wrappers for memory and text-based types
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.
* .
@jozkee

Copy link
Copy Markdown
Member

/backport to release/11.0-preview6

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview6 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@jozkee backporting to release/11.0-preview6 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: First API proposal implementationUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/ref/System.Memory.csM	src/libraries/System.Memory/tests/System.Memory.Tests.csprojM	src/libraries/System.Private.CoreLib/src/Resources/Strings.resxM	src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsM	src/libraries/System.Runtime/ref/System.Runtime.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/ref/System.Memory.csAuto-merging src/libraries/System.Memory/tests/System.Memory.Tests.csprojAuto-merging src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAuto-merging src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsAuto-merging src/libraries/System.Runtime/ref/System.Runtime.csApplying: API replacements in production codeApplying: Implementation update based on latest API Review final consensusApplying: Address PR feedback. MemoryStream base change. Spillover buffer for Convert edge case. Flush strategy update.Applying: Address PR feedbackApplying: Address PR feedback: fix StringStream flush offset, WritableMemoryStream length/seek semantics, ReadOnlySequenceStream safety, and consolidate testsApplying: Address PR feedback: remove redundant code, improve test coverage and structureUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csM	src/libraries/System.Net.Http/src/System.Net.Http.csprojM	src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csM	src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csM	src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csAuto-merging src/libraries/System.Net.Http/src/System.Net.Http.csprojAuto-merging src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csAuto-merging src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csCONFLICT (content): Merge conflict in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0007 Address PR feedback: remove redundant code, improve test coverage and structureError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

jozkee pushed a commit that referenced this pull request Jun 25, 2026
… types (#129811)
Backport of #126669 to
release/11.0-preview6. See that PR for full details.
Adds new public stream wrapper APIs (`StringStream`,
`ReadOnlyMemoryStream`, `WritableMemoryStream`,
`ReadOnlySequenceStream`).
Fixes#82801.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 25, 2026
SimonCropp added a commit to SimonCropp/Polyfill 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
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Fixes#82801
Introduces standardized stream wrappers for text and memory types as
public sealed classes (`StringStream`, `ReadOnlyMemoryStream`,
`WritableMemoryStream`, and `ReadOnlySequenceStream` ) as approved in
[API
review](#82801 (comment))
([video](https://www.youtube.com/watch?v=T7xc7rARCEw&t=0h9m41s)).
### What's included
- `StringStream` (`System.IO`, CoreLib): non-seekable, read-only stream
that encodes `string` or `ReadOnlyMemory<char>` on-the-fly. Encoding is
required (no default). Never emits BOMs.
- `ReadOnlyMemoryStream` (`System.IO`, CoreLib): seekable, read-only
stream over `ReadOnlyMemory<byte>`
- `WritableMemoryStream` (`System.IO`, CoreLib): seekable, read-write
stream over `Memory<byte>` with fixed capacity
- `ReadOnlySequenceStream` (`System.Buffers`, System.Memory): seekable,
read-only stream over `ReadOnlySequence<byte>`
- Ref assembly updates for `System.Runtime` and `System.Memory`
- Updated 3 internal call sites (`ReadOnlyMemoryContent`,
`XmlPreloadedResolver`, `JsonXmlDataContract`) to use the new types
- Conformance and behavioral tests for all 4 types
### Implementation notes
- All types are `public sealed` with direct constructors: the review
moved away from factory methods on `Stream` to avoid derived-type
IntelliSense noise
- `StringStream` encodes directly into the caller's buffer in `Read()`
rather than using an internal byte buffer
- `ReadOnlyMemoryStream` and `WritableMemoryStream` derive from
`MemoryStream`.
- `TryGetBuffer` returns false and `GetBuffer` throws on the memory
stream types (no `publiclyVisible` support for now)
### Limitations
- The internal
[shared-source](https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/ReadOnlyMemoryStream.cs)
`ReadOnlyMemoryStream` in `Common/` cannot be fully replaced:
- `System.Memory.Data` multi-targets `netstandard2.0` where the new
public type doesn't exist.
- `System.Net.Http` (net11.0 only) can adopt it directly.
### Follow-up work
- `IBufferWriter<byte>` → `Stream` wrapper (separate proposal per
[#100434](#100434))
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add Stream wrappers for memory and text-based types

8 participants

@ViveliDuCh@SimonCropp@jozkee@stephentoub@adamsitnik@bartonjs@tarekgh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add Stream wrappers for memory and text-based types - #126669

Merged
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api
Jun 24, 2026
Merged

Add Stream wrappers for memory and text-based types#126669
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api

Conversation

@ViveliDuCh

@ViveliDuChViveliDuCh commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fixes#82801

Introduces standardized stream wrappers for text and memory types as public sealed classes (StringStream, ReadOnlyMemoryStream, WritableMemoryStream, and ReadOnlySequenceStream ) as approved in API review (video).

What's included

  • StringStream (System.IO, CoreLib): non-seekable, read-only stream that encodes string or ReadOnlyMemory<char> on-the-fly. Encoding is required (no default). Never emits BOMs.
  • ReadOnlyMemoryStream (System.IO, CoreLib): seekable, read-only stream over ReadOnlyMemory<byte>
  • WritableMemoryStream (System.IO, CoreLib): seekable, read-write stream over Memory<byte> with fixed capacity
  • ReadOnlySequenceStream (System.Buffers, System.Memory): seekable, read-only stream over ReadOnlySequence<byte>
  • Ref assembly updates for System.Runtime and System.Memory
  • Updated 3 internal call sites (ReadOnlyMemoryContent, XmlPreloadedResolver, JsonXmlDataContract) to use the new types
  • Conformance and behavioral tests for all 4 types

Implementation notes

  • All types are public sealed with direct constructors: the review moved away from factory methods on Stream to avoid derived-type IntelliSense noise
  • StringStream encodes directly into the caller's buffer in Read() rather than using an internal byte buffer
  • ReadOnlyMemoryStream and WritableMemoryStream derive from MemoryStream.
  • TryGetBuffer returns false and GetBuffer throws on the memory stream types (no publiclyVisible support for now)

Limitations

  • The internal shared-sourceReadOnlyMemoryStream in Common/ cannot be fully replaced:
    • System.Memory.Data multi-targets netstandard2.0 where the new public type doesn't exist.
    • System.Net.Http (net11.0 only) can adopt it directly.

Follow-up work

  • IBufferWriter<byte>Stream wrapper (separate proposal per #100434)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces new standardized Stream wrapper types across CoreLib and System.Memory, aligning with the approved API shape from #82801 and updating a few internal call sites to use the new wrappers.

Changes:

  • Added new public sealed stream wrappers: StringStream, ReadOnlyMemoryStream, WritableMemoryStream (CoreLib) and ReadOnlySequenceStream (System.Memory).
  • Updated reference assemblies and project files to expose/compile the new APIs.
  • Added conformance + targeted behavioral tests, and updated select internal consumers to use StringStream.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/IO/StringStream.csImplements the new StringStream API (read-only, non-seekable, on-the-fly encoding).
src/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.csImplements seekable read-only stream over ReadOnlyMemory<byte>.
src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csImplements seekable fixed-capacity read/write stream over Memory<byte>.
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsWires new CoreLib stream wrapper source files into the build.
src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAdds a new resource string entry (currently appears unused).
src/libraries/System.Runtime/ref/System.Runtime.csUpdates public API surface to include the new stream wrapper types (and a small ref signature normalization change).
src/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csprojIncludes the new test files in the System.IO test project.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamConformanceTests.csAdds conformance coverage for StringStream (string + ReadOnlyMemory<char> overloads).
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAdds targeted StringStream(string, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAdds targeted StringStream(ReadOnlyMemory<char>, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAdds conformance coverage for ReadOnlyMemoryStream.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamTests.csAdds targeted ReadOnlyMemoryStream behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAdds conformance coverage for WritableMemoryStream (with some overridden tests).
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csAdds targeted WritableMemoryStream behavioral tests.
src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csImplements ReadOnlySequenceStream over ReadOnlySequence<byte>.
src/libraries/System.Memory/src/System.Memory.csprojIncludes the new ReadOnlySequenceStream source file in System.Memory.
src/libraries/System.Memory/src/Resources/Strings.resxAdds SR strings needed for stream-like exception messages in System.Memory.
src/libraries/System.Memory/ref/System.Memory.csAdds ReadOnlySequenceStream to the System.Memory ref surface.
src/libraries/System.Memory/tests/System.Memory.Tests.csprojAdds tests for ReadOnlySequenceStream and references StreamConformanceTests.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStreamTests.csAdds targeted behavioral tests for multi-segment ReadOnlySequenceStream scenarios.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStream.ConformanceTests.csAdds conformance coverage for ReadOnlySequenceStream.
src/libraries/System.Private.Xml/src/System/Xml/Resolvers/XmlPreloadedResolver.csSwitches internal string-to-stream conversion to StringStream.
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csSwitches internal string-to-stream conversion to StringStream.
Comments suppressed due to low confidence (1)

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.cs:38

  • Variable is still named 'memoryStream' but the implementation is now StringStream (not a MemoryStream). Rename the local to avoid implying the stream is seekable/in-memory-buffered (e.g., 'xmlContentStream').
 Stream memoryStream = new StringStream(xmlContent, Encoding.UTF8);
object? xmlValue;
XmlDictionaryReaderQuotas? quotas = ((JsonReaderDelegator)jsonReader).ReaderQuotas;
if (quotas == null)
{
xmlValue = dataContractSerializer.ReadObject(memoryStream);

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/ref/System.Runtime.cs
Comment threadsrc/libraries/System.Private.CoreLib/src/Resources/Strings.resx Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Memory/ref/System.Memory.cs
CopilotAI review requested due to automatic review settings April 9, 2026 08:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csproj Outdated
Comment threadsrc/libraries/System.Memory/src/System.Memory.csproj Outdated
Comment threadsrc/libraries/System.Memory/tests/System.Memory.Tests.csproj Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings April 13, 2026 19:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings June 23, 2026 23:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@SimonCropp

Copy link
Copy Markdown
Contributor

awesome. that .net preview will this be in?

SimonCropp added a commit to SimonCropp/Polyfill that referenced this pull request Jun 24, 2026
* Add Stream wrappers for memory and text-based types
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.
* .
@jozkee

Copy link
Copy Markdown
Member

/backport to release/11.0-preview6

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview6 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@jozkee backporting to release/11.0-preview6 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: First API proposal implementationUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/ref/System.Memory.csM	src/libraries/System.Memory/tests/System.Memory.Tests.csprojM	src/libraries/System.Private.CoreLib/src/Resources/Strings.resxM	src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsM	src/libraries/System.Runtime/ref/System.Runtime.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/ref/System.Memory.csAuto-merging src/libraries/System.Memory/tests/System.Memory.Tests.csprojAuto-merging src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAuto-merging src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsAuto-merging src/libraries/System.Runtime/ref/System.Runtime.csApplying: API replacements in production codeApplying: Implementation update based on latest API Review final consensusApplying: Address PR feedback. MemoryStream base change. Spillover buffer for Convert edge case. Flush strategy update.Applying: Address PR feedbackApplying: Address PR feedback: fix StringStream flush offset, WritableMemoryStream length/seek semantics, ReadOnlySequenceStream safety, and consolidate testsApplying: Address PR feedback: remove redundant code, improve test coverage and structureUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csM	src/libraries/System.Net.Http/src/System.Net.Http.csprojM	src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csM	src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csM	src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csAuto-merging src/libraries/System.Net.Http/src/System.Net.Http.csprojAuto-merging src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csAuto-merging src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csCONFLICT (content): Merge conflict in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0007 Address PR feedback: remove redundant code, improve test coverage and structureError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

jozkee pushed a commit that referenced this pull request Jun 25, 2026
… types (#129811)
Backport of #126669 to
release/11.0-preview6. See that PR for full details.
Adds new public stream wrapper APIs (`StringStream`,
`ReadOnlyMemoryStream`, `WritableMemoryStream`,
`ReadOnlySequenceStream`).
Fixes#82801.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 25, 2026
SimonCropp added a commit to SimonCropp/Polyfill 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
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Fixes#82801
Introduces standardized stream wrappers for text and memory types as
public sealed classes (`StringStream`, `ReadOnlyMemoryStream`,
`WritableMemoryStream`, and `ReadOnlySequenceStream` ) as approved in
[API
review](#82801 (comment))
([video](https://www.youtube.com/watch?v=T7xc7rARCEw&t=0h9m41s)).
### What's included
- `StringStream` (`System.IO`, CoreLib): non-seekable, read-only stream
that encodes `string` or `ReadOnlyMemory<char>` on-the-fly. Encoding is
required (no default). Never emits BOMs.
- `ReadOnlyMemoryStream` (`System.IO`, CoreLib): seekable, read-only
stream over `ReadOnlyMemory<byte>`
- `WritableMemoryStream` (`System.IO`, CoreLib): seekable, read-write
stream over `Memory<byte>` with fixed capacity
- `ReadOnlySequenceStream` (`System.Buffers`, System.Memory): seekable,
read-only stream over `ReadOnlySequence<byte>`
- Ref assembly updates for `System.Runtime` and `System.Memory`
- Updated 3 internal call sites (`ReadOnlyMemoryContent`,
`XmlPreloadedResolver`, `JsonXmlDataContract`) to use the new types
- Conformance and behavioral tests for all 4 types
### Implementation notes
- All types are `public sealed` with direct constructors: the review
moved away from factory methods on `Stream` to avoid derived-type
IntelliSense noise
- `StringStream` encodes directly into the caller's buffer in `Read()`
rather than using an internal byte buffer
- `ReadOnlyMemoryStream` and `WritableMemoryStream` derive from
`MemoryStream`.
- `TryGetBuffer` returns false and `GetBuffer` throws on the memory
stream types (no `publiclyVisible` support for now)
### Limitations
- The internal
[shared-source](https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/ReadOnlyMemoryStream.cs)
`ReadOnlyMemoryStream` in `Common/` cannot be fully replaced:
- `System.Memory.Data` multi-targets `netstandard2.0` where the new
public type doesn't exist.
- `System.Net.Http` (net11.0 only) can adopt it directly.
### Follow-up work
- `IBufferWriter<byte>` → `Stream` wrapper (separate proposal per
[#100434](#100434))
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add Stream wrappers for memory and text-based types

8 participants

@ViveliDuCh@SimonCropp@jozkee@stephentoub@adamsitnik@bartonjs@tarekgh
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add Stream wrappers for memory and text-based types - #126669

Merged
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api
Jun 24, 2026
Merged

Add Stream wrappers for memory and text-based types#126669
ViveliDuCh merged 23 commits into
dotnet:mainfrom
ViveliDuCh:stream-wrappers-api

Conversation

@ViveliDuCh

@ViveliDuChViveliDuCh commented Apr 8, 2026

Copy link
Copy Markdown
Member

Fixes#82801

Introduces standardized stream wrappers for text and memory types as public sealed classes (StringStream, ReadOnlyMemoryStream, WritableMemoryStream, and ReadOnlySequenceStream ) as approved in API review (video).

What's included

  • StringStream (System.IO, CoreLib): non-seekable, read-only stream that encodes string or ReadOnlyMemory<char> on-the-fly. Encoding is required (no default). Never emits BOMs.
  • ReadOnlyMemoryStream (System.IO, CoreLib): seekable, read-only stream over ReadOnlyMemory<byte>
  • WritableMemoryStream (System.IO, CoreLib): seekable, read-write stream over Memory<byte> with fixed capacity
  • ReadOnlySequenceStream (System.Buffers, System.Memory): seekable, read-only stream over ReadOnlySequence<byte>
  • Ref assembly updates for System.Runtime and System.Memory
  • Updated 3 internal call sites (ReadOnlyMemoryContent, XmlPreloadedResolver, JsonXmlDataContract) to use the new types
  • Conformance and behavioral tests for all 4 types

Implementation notes

  • All types are public sealed with direct constructors: the review moved away from factory methods on Stream to avoid derived-type IntelliSense noise
  • StringStream encodes directly into the caller's buffer in Read() rather than using an internal byte buffer
  • ReadOnlyMemoryStream and WritableMemoryStream derive from MemoryStream.
  • TryGetBuffer returns false and GetBuffer throws on the memory stream types (no publiclyVisible support for now)

Limitations

  • The internal shared-sourceReadOnlyMemoryStream in Common/ cannot be fully replaced:
    • System.Memory.Data multi-targets netstandard2.0 where the new public type doesn't exist.
    • System.Net.Http (net11.0 only) can adopt it directly.

Follow-up work

  • IBufferWriter<byte>Stream wrapper (separate proposal per #100434)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces new standardized Stream wrapper types across CoreLib and System.Memory, aligning with the approved API shape from #82801 and updating a few internal call sites to use the new wrappers.

Changes:

  • Added new public sealed stream wrappers: StringStream, ReadOnlyMemoryStream, WritableMemoryStream (CoreLib) and ReadOnlySequenceStream (System.Memory).
  • Updated reference assemblies and project files to expose/compile the new APIs.
  • Added conformance + targeted behavioral tests, and updated select internal consumers to use StringStream.

Reviewed changes

Copilot reviewed 23 out of 23 changed files in this pull request and generated 9 comments.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/IO/StringStream.csImplements the new StringStream API (read-only, non-seekable, on-the-fly encoding).
src/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.csImplements seekable read-only stream over ReadOnlyMemory<byte>.
src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csImplements seekable fixed-capacity read/write stream over Memory<byte>.
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsWires new CoreLib stream wrapper source files into the build.
src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAdds a new resource string entry (currently appears unused).
src/libraries/System.Runtime/ref/System.Runtime.csUpdates public API surface to include the new stream wrapper types (and a small ref signature normalization change).
src/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csprojIncludes the new test files in the System.IO test project.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamConformanceTests.csAdds conformance coverage for StringStream (string + ReadOnlyMemory<char> overloads).
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAdds targeted StringStream(string, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAdds targeted StringStream(ReadOnlyMemory<char>, Encoding) behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAdds conformance coverage for ReadOnlyMemoryStream.
src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamTests.csAdds targeted ReadOnlyMemoryStream behavioral tests.
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAdds conformance coverage for WritableMemoryStream (with some overridden tests).
src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csAdds targeted WritableMemoryStream behavioral tests.
src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csImplements ReadOnlySequenceStream over ReadOnlySequence<byte>.
src/libraries/System.Memory/src/System.Memory.csprojIncludes the new ReadOnlySequenceStream source file in System.Memory.
src/libraries/System.Memory/src/Resources/Strings.resxAdds SR strings needed for stream-like exception messages in System.Memory.
src/libraries/System.Memory/ref/System.Memory.csAdds ReadOnlySequenceStream to the System.Memory ref surface.
src/libraries/System.Memory/tests/System.Memory.Tests.csprojAdds tests for ReadOnlySequenceStream and references StreamConformanceTests.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStreamTests.csAdds targeted behavioral tests for multi-segment ReadOnlySequenceStream scenarios.
src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceStream.ConformanceTests.csAdds conformance coverage for ReadOnlySequenceStream.
src/libraries/System.Private.Xml/src/System/Xml/Resolvers/XmlPreloadedResolver.csSwitches internal string-to-stream conversion to StringStream.
src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csSwitches internal string-to-stream conversion to StringStream.
Comments suppressed due to low confidence (1)

src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.cs:38

  • Variable is still named 'memoryStream' but the implementation is now StringStream (not a MemoryStream). Rename the local to avoid implying the stream is seekable/in-memory-buffered (e.g., 'xmlContentStream').
 Stream memoryStream = new StringStream(xmlContent, Encoding.UTF8);
object? xmlValue;
XmlDictionaryReaderQuotas? quotas = ((JsonReaderDelegator)jsonReader).ReaderQuotas;
if (quotas == null)
{
xmlValue = dataContractSerializer.ReadObject(memoryStream);

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/ref/System.Runtime.cs
Comment threadsrc/libraries/System.Private.CoreLib/src/Resources/Strings.resx Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Memory/ref/System.Memory.cs
CopilotAI review requested due to automatic review settings April 9, 2026 08:01

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 10 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Runtime/tests/System.IO.Tests/System.IO.Tests.csproj Outdated
Comment threadsrc/libraries/System.Memory/src/System.Memory.csproj Outdated
Comment threadsrc/libraries/System.Memory/tests/System.Memory.Tests.csproj Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings April 13, 2026 19:23

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/ReadOnlyMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/StringStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
Comment threadsrc/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.cs Outdated
CopilotAI review requested due to automatic review settings June 23, 2026 23:25

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 28 out of 29 changed files in this pull request and generated 1 comment.

@SimonCropp

Copy link
Copy Markdown
Contributor

awesome. that .net preview will this be in?

SimonCropp added a commit to SimonCropp/Polyfill that referenced this pull request Jun 24, 2026
* Add Stream wrappers for memory and text-based types
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.
* .
@jozkee

Copy link
Copy Markdown
Member

/backport to release/11.0-preview6

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/11.0-preview6 (link to workflow run)

@github-actions

Copy link
Copy Markdown
Contributor

@jozkee backporting to release/11.0-preview6 failed, the patch most likely resulted in conflicts. Please backport manually!

git am output
$ git am --3way --empty=keep --ignore-whitespace --keep-non-patch changes.patchApplying: First API proposal implementationUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/ref/System.Memory.csM	src/libraries/System.Memory/tests/System.Memory.Tests.csprojM	src/libraries/System.Private.CoreLib/src/Resources/Strings.resxM	src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsM	src/libraries/System.Runtime/ref/System.Runtime.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/ref/System.Memory.csAuto-merging src/libraries/System.Memory/tests/System.Memory.Tests.csprojAuto-merging src/libraries/System.Private.CoreLib/src/Resources/Strings.resxAuto-merging src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitemsAuto-merging src/libraries/System.Runtime/ref/System.Runtime.csApplying: API replacements in production codeApplying: Implementation update based on latest API Review final consensusApplying: Address PR feedback. MemoryStream base change. Spillover buffer for Convert edge case. Flush strategy update.Applying: Address PR feedbackApplying: Address PR feedback: fix StringStream flush offset, WritableMemoryStream length/seek semantics, ReadOnlySequenceStream safety, and consolidate testsApplying: Address PR feedback: remove redundant code, improve test coverage and structureUsing index info to reconstruct a base tree...M	src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csM	src/libraries/System.Net.Http/src/System.Net.Http.csprojM	src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csM	src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csM	src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csM	src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csM	src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csFalling back to patching base and 3-way merge...Auto-merging src/libraries/System.Memory/src/System/Buffers/ReadOnlySequenceStream.csAuto-merging src/libraries/System.Net.Http/src/System.Net.Http.csprojAuto-merging src/libraries/System.Private.CoreLib/src/System/IO/WritableMemoryStream.csAuto-merging src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csCONFLICT (content): Merge conflict in src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonXmlDataContract.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/ReadOnlyMemoryStream/ReadOnlyMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_Memory.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/StringStream/StringStreamTests_String.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamConformanceTests.csAuto-merging src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.csCONFLICT (content): Merge conflict in src/libraries/System.Runtime/tests/System.IO.Tests/WritableMemoryStream/WritableMemoryStreamTests.cserror: Failed to merge in the changes.hint: Use 'git am --show-current-patch=diff' to see the failed patchhint: When you have resolved this problem, run "git am --continue".hint: If you prefer to skip this patch, run "git am --skip" instead.hint: To restore the original branch and stop patching, run "git am --abort".hint: Disable this message with "git config set advice.mergeConflict false"Patch failed at 0007 Address PR feedback: remove redundant code, improve test coverage and structureError: The process '/usr/bin/git' failed with exit code 128

Link to workflow output

jozkee pushed a commit that referenced this pull request Jun 25, 2026
… types (#129811)
Backport of #126669 to
release/11.0-preview6. See that PR for full details.
Adds new public stream wrapper APIs (`StringStream`,
`ReadOnlyMemoryStream`, `WritableMemoryStream`,
`ReadOnlySequenceStream`).
Fixes#82801.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jun 25, 2026
SimonCropp added a commit to SimonCropp/Polyfill 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
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
Fixes#82801
Introduces standardized stream wrappers for text and memory types as
public sealed classes (`StringStream`, `ReadOnlyMemoryStream`,
`WritableMemoryStream`, and `ReadOnlySequenceStream` ) as approved in
[API
review](#82801 (comment))
([video](https://www.youtube.com/watch?v=T7xc7rARCEw&t=0h9m41s)).
### What's included
- `StringStream` (`System.IO`, CoreLib): non-seekable, read-only stream
that encodes `string` or `ReadOnlyMemory<char>` on-the-fly. Encoding is
required (no default). Never emits BOMs.
- `ReadOnlyMemoryStream` (`System.IO`, CoreLib): seekable, read-only
stream over `ReadOnlyMemory<byte>`
- `WritableMemoryStream` (`System.IO`, CoreLib): seekable, read-write
stream over `Memory<byte>` with fixed capacity
- `ReadOnlySequenceStream` (`System.Buffers`, System.Memory): seekable,
read-only stream over `ReadOnlySequence<byte>`
- Ref assembly updates for `System.Runtime` and `System.Memory`
- Updated 3 internal call sites (`ReadOnlyMemoryContent`,
`XmlPreloadedResolver`, `JsonXmlDataContract`) to use the new types
- Conformance and behavioral tests for all 4 types
### Implementation notes
- All types are `public sealed` with direct constructors: the review
moved away from factory methods on `Stream` to avoid derived-type
IntelliSense noise
- `StringStream` encodes directly into the caller's buffer in `Read()`
rather than using an internal byte buffer
- `ReadOnlyMemoryStream` and `WritableMemoryStream` derive from
`MemoryStream`.
- `TryGetBuffer` returns false and `GetBuffer` throws on the memory
stream types (no `publiclyVisible` support for now)
### Limitations
- The internal
[shared-source](https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/System/IO/ReadOnlyMemoryStream.cs)
`ReadOnlyMemoryStream` in `Common/` cannot be fully replaced:
- `System.Memory.Data` multi-targets `netstandard2.0` where the new
public type doesn't exist.
- `System.Net.Http` (net11.0 only) can adopt it directly.
### Follow-up work
- `IBufferWriter<byte>` → `Stream` wrapper (separate proposal per
[#100434](#100434))
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[API Proposal]: Add Stream wrappers for memory and text-based types

8 participants

@ViveliDuCh@SimonCropp@jozkee@stephentoub@adamsitnik@bartonjs@tarekgh