diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContextSerializer.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContextSerializer.cs index 80d6aae4fac89..3fa34712db4a5 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContextSerializer.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/Design/DesigntimeLicenseContextSerializer.cs @@ -84,17 +84,20 @@ public StreamWrapper(Stream stream) public override void Flush() => _stream.Flush(); - public override int Read(byte[] buffer, int offset, int count) + public override int Read(byte[] buffer, int offset, int count) => + Read(new Span(buffer, offset, count)); + + public override int Read(Span buffer) { Debug.Assert(_stream.Position != 0, "Expected the first byte to be read first"); if (_stream.Position == 1) { Debug.Assert(_readFirstByte == true); // Add the first byte read by ReadByte into buffer here - buffer[offset] = _firstByte; - return _stream.Read(buffer, offset + 1, count - 1) + 1; + buffer[0] = _firstByte; + return _stream.Read(buffer.Slice(1)) + 1; } - return _stream.Read(buffer, offset, count); + return _stream.Read(buffer); } public override long Seek(long offset, SeekOrigin origin) => _stream.Seek(offset, origin); diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs index 90402cfc33e78..00fc6c2adac59 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SqlXml.cs @@ -424,6 +424,22 @@ public override int Read(byte[] buffer, int offset, int count) return iBytesRead; } + // Duplicate the Read(byte[]) logic here instead of refactoring both to use Spans + // in case the backing _stream doesn't override Read(Span). + public override int Read(Span buffer) + { + ThrowIfStreamClosed(nameof(Read)); + ThrowIfStreamCannotRead(nameof(Read)); + + if (_stream.CanSeek && _stream.Position != _lPosition) + _stream.Seek(_lPosition, SeekOrigin.Begin); + + int iBytesRead = _stream.Read(buffer); + _lPosition += iBytesRead; + + return iBytesRead; + } + public override void Write(byte[] buffer, int offset, int count) { ThrowIfStreamClosed(nameof(Write)); diff --git a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs index 4b2df41a9838d..e3f3b42e77531 100644 --- a/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs +++ b/src/libraries/System.IO.Packaging/src/System/IO/Packaging/ZipWrappingStream.cs @@ -67,6 +67,22 @@ int count return _baseStream.Read(buffer, offset, count); } +#if NETCOREAPP + public override void Write( + ReadOnlySpan buffer + ) + { + _baseStream.Write(buffer); + } + + public override int Read( + Span buffer + ) + { + return _baseStream.Read(buffer); + } +#endif + public override void SetLength( long value ) diff --git a/src/libraries/System.Net.Requests/src/System/Net/FtpDataStream.cs b/src/libraries/System.Net.Requests/src/System/Net/FtpDataStream.cs index fb86000f41774..3582c7429d29c 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/FtpDataStream.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/FtpDataStream.cs @@ -193,6 +193,27 @@ public override int Read(byte[] buffer, int offset, int size) return readBytes; } + public override int Read(Span buffer) + { + CheckError(); + int readBytes; + try + { + readBytes = _networkStream.Read(buffer); + } + catch + { + CheckError(); + throw; + } + if (readBytes == 0) + { + _isFullyRead = true; + Close(); + } + return readBytes; + } + public override void Write(byte[] buffer, int offset, int size) { CheckError(); @@ -207,6 +228,20 @@ public override void Write(byte[] buffer, int offset, int size) } } + public override void Write(ReadOnlySpan buffer) + { + CheckError(); + try + { + _networkStream.Write(buffer); + } + catch + { + CheckError(); + throw; + } + } + private void AsyncReadCallback(IAsyncResult ar) { LazyAsyncResult userResult = (LazyAsyncResult)ar.AsyncState!; diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs index 8f30f153be140..f6a0516d24bac 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonEncodingStreamWrapper.cs @@ -174,7 +174,10 @@ public override void Flush() _stream.Flush(); } - public override int Read(byte[] buffer, int offset, int count) + public override int Read(byte[] buffer, int offset, int count) => + Read(new Span(buffer, offset, count)); + + public override int Read(Span buffer) { try { @@ -182,7 +185,7 @@ public override int Read(byte[] buffer, int offset, int count) { if (_encodingCode == SupportedEncoding.UTF8) { - return _stream.Read(buffer, offset, count); + return _stream.Read(buffer); } Debug.Assert(_bytes != null); @@ -206,11 +209,13 @@ public override int Read(byte[] buffer, int offset, int count) } // Give them bytes + int count = buffer.Length; if (_byteCount < count) { count = _byteCount; } - Buffer.BlockCopy(_bytes!, _byteOffset, buffer, offset, count); + + _bytes.AsSpan(_byteOffset, count).CopyTo(buffer); _byteOffset += count; _byteCount -= count; return count; diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs index e0fe24ba58163..7d9bab87855fd 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/EncodingStreamWrapper.cs @@ -593,14 +593,17 @@ public override int ReadByte() return _byteBuffer[0]; } - public override int Read(byte[] buffer, int offset, int count) + public override int Read(byte[] buffer, int offset, int count) => + Read(new Span(buffer, offset, count)); + + public override int Read(Span buffer) { try { if (_byteCount == 0) { if (_encodingCode == SupportedEncoding.UTF8) - return _stream.Read(buffer, offset, count); + return _stream.Read(buffer); Debug.Assert(_bytes != null); Debug.Assert(_chars != null); @@ -622,9 +625,11 @@ public override int Read(byte[] buffer, int offset, int count) } // Give them bytes + int count = buffer.Length; if (_byteCount < count) count = _byteCount; - Buffer.BlockCopy(_bytes!, _byteOffset, buffer, offset, count); + + _bytes.AsSpan(_byteOffset, count).CopyTo(buffer); _byteOffset += count; _byteCount -= count; return count; diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs index 4dc115b73882f..26dc9290ab4e6 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ImmutableMemoryStream.cs @@ -72,6 +72,18 @@ public override int Read(byte[] buffer, int offset, int count) return result; } +#if NETCOREAPP + // Duplicate the Read(byte[]) logic here instead of refactoring both to use Spans + // so we don't affect perf on .NET Framework. + public override int Read(Span buffer) + { + int result = Math.Min(buffer.Length, _array.Length - _position); + _array.AsSpan(_position, result).CopyTo(buffer); + _position += result; + return result; + } +#endif + public override long Seek(long offset, SeekOrigin origin) { long target; diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs index e0af775a3116b..abb5c8ff1f6af 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/ReadOnlyUnmanagedMemoryStream.cs @@ -36,6 +36,18 @@ public override int Read(byte[] buffer, int offset, int count) return bytesRead; } +#if NETCOREAPP + // Duplicate the Read(byte[]) logic here instead of refactoring both to use Spans + // so we don't affect perf on .NET Framework. + public override int Read(Span buffer) + { + int bytesRead = Math.Min(buffer.Length, _length - _position); + new Span(_data + _position, bytesRead).CopyTo(buffer); + _position += bytesRead; + return bytesRead; + } +#endif + public override void Flush() { }