Add nullable to WebUtilities (#22543)

This commit is contained in:
Pranav K 2020-06-08 10:48:43 -07:00 committed by GitHub
parent aeb28d4b83
commit cd81d48766
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 154 additions and 140 deletions

View File

@ -2,6 +2,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(DefaultNetCoreTargetFramework)</TargetFrameworks>
<Nullable>annotations</Nullable>
</PropertyGroup>
<ItemGroup Condition="'$(TargetFramework)' == '$(DefaultNetCoreTargetFramework)'">
<Compile Include="Microsoft.AspNetCore.WebUtilities.netcoreapp.cs" />

View File

@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.WebUtilities
public bool InMemory { get { throw null; } }
public override long Length { get { throw null; } }
public override long Position { get { throw null; } set { } }
public string TempFileName { get { throw null; } }
public string? TempFileName { get { throw null; } }
protected override void Dispose(bool disposing) { }
[System.Diagnostics.DebuggerStepThroughAttribute]
public override System.Threading.Tasks.ValueTask DisposeAsync() { throw null; }
@ -67,7 +67,7 @@ namespace Microsoft.AspNetCore.WebUtilities
}
public sealed partial class FileBufferingWriteStream : System.IO.Stream
{
public FileBufferingWriteStream(int memoryThreshold = 32768, long? bufferLimit = default(long?), System.Func<string> tempFileDirectoryAccessor = null) { }
public FileBufferingWriteStream(int memoryThreshold = 32768, long? bufferLimit = default(long?), System.Func<string>? tempFileDirectoryAccessor = null) { }
public override bool CanRead { get { throw null; } }
public override bool CanSeek { get { throw null; } }
public override bool CanWrite { get { throw null; } }
@ -91,16 +91,16 @@ namespace Microsoft.AspNetCore.WebUtilities
public partial class FileMultipartSection
{
public FileMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section) { }
public FileMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section, Microsoft.Net.Http.Headers.ContentDispositionHeaderValue header) { }
public FileMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section, Microsoft.Net.Http.Headers.ContentDispositionHeaderValue? header) { }
public string FileName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public System.IO.Stream FileStream { get { throw null; } }
public System.IO.Stream? FileStream { get { throw null; } }
public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public Microsoft.AspNetCore.WebUtilities.MultipartSection Section { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
}
public partial class FormMultipartSection
{
public FormMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section) { }
public FormMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section, Microsoft.Net.Http.Headers.ContentDispositionHeaderValue header) { }
public FormMultipartSection(Microsoft.AspNetCore.WebUtilities.MultipartSection section, Microsoft.Net.Http.Headers.ContentDispositionHeaderValue? header) { }
public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public Microsoft.AspNetCore.WebUtilities.MultipartSection Section { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } }
public System.Threading.Tasks.Task<string> GetValueAsync() { throw null; }
@ -149,9 +149,9 @@ namespace Microsoft.AspNetCore.WebUtilities
public override System.Threading.Tasks.Task<int> ReadAsync(char[] buffer, int index, int count) { throw null; }
[System.Diagnostics.DebuggerStepThroughAttribute]
public override System.Threading.Tasks.ValueTask<int> ReadAsync(System.Memory<char> buffer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public override string ReadLine() { throw null; }
public override string? ReadLine() { throw null; }
[System.Diagnostics.DebuggerStepThroughAttribute]
public override System.Threading.Tasks.Task<string> ReadLineAsync() { throw null; }
public override System.Threading.Tasks.Task<string?> ReadLineAsync() { throw null; }
[System.Diagnostics.DebuggerStepThroughAttribute]
public override System.Threading.Tasks.Task<string> ReadToEndAsync() { throw null; }
}
@ -169,11 +169,11 @@ namespace Microsoft.AspNetCore.WebUtilities
public override void Write(char value) { }
public override void Write(char[] values, int index, int count) { }
public override void Write(System.ReadOnlySpan<char> value) { }
public override void Write(string value) { }
public override void Write(string? value) { }
public override System.Threading.Tasks.Task WriteAsync(char value) { throw null; }
public override System.Threading.Tasks.Task WriteAsync(char[] values, int index, int count) { throw null; }
public override System.Threading.Tasks.Task WriteAsync(System.ReadOnlyMemory<char> value, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public override System.Threading.Tasks.Task WriteAsync(string value) { throw null; }
public override System.Threading.Tasks.Task WriteAsync(string? value) { throw null; }
public override void WriteLine(System.ReadOnlySpan<char> value) { }
public override System.Threading.Tasks.Task WriteLineAsync(System.ReadOnlyMemory<char> value, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
@ -198,22 +198,22 @@ namespace Microsoft.AspNetCore.WebUtilities
public int HeadersCountLimit { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public int HeadersLengthLimit { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
[System.Diagnostics.DebuggerStepThroughAttribute]
public System.Threading.Tasks.Task<Microsoft.AspNetCore.WebUtilities.MultipartSection> ReadNextSectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public System.Threading.Tasks.Task<Microsoft.AspNetCore.WebUtilities.MultipartSection?> ReadNextSectionAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public partial class MultipartSection
{
public MultipartSection() { }
public long? BaseStreamOffset { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public System.IO.Stream Body { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public string ContentDisposition { get { throw null; } }
public string ContentType { get { throw null; } }
public System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues> Headers { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public System.IO.Stream? Body { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
public string? ContentDisposition { get { throw null; } }
public string? ContentType { get { throw null; } }
public System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues>? Headers { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } }
}
public static partial class MultipartSectionConverterExtensions
{
public static Microsoft.AspNetCore.WebUtilities.FileMultipartSection AsFileSection(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) { throw null; }
public static Microsoft.AspNetCore.WebUtilities.FormMultipartSection AsFormDataSection(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) { throw null; }
public static Microsoft.Net.Http.Headers.ContentDispositionHeaderValue GetContentDispositionHeader(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) { throw null; }
public static Microsoft.AspNetCore.WebUtilities.FileMultipartSection? AsFileSection(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) { throw null; }
public static Microsoft.AspNetCore.WebUtilities.FormMultipartSection? AsFormDataSection(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) { throw null; }
public static Microsoft.Net.Http.Headers.ContentDispositionHeaderValue? GetContentDispositionHeader(this Microsoft.AspNetCore.WebUtilities.MultipartSection section) { throw null; }
}
public static partial class MultipartSectionStreamExtensions
{
@ -222,11 +222,11 @@ namespace Microsoft.AspNetCore.WebUtilities
}
public static partial class QueryHelpers
{
public static string AddQueryString(string uri, System.Collections.Generic.IDictionary<string, string> queryString) { throw null; }
public static string AddQueryString(string uri, System.Collections.Generic.IDictionary<string, string?> queryString) { throw null; }
public static string AddQueryString(string uri, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, Microsoft.Extensions.Primitives.StringValues>> queryString) { throw null; }
public static string AddQueryString(string uri, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string>> queryString) { throw null; }
public static string AddQueryString(string uri, System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, string?>> queryString) { throw null; }
public static string AddQueryString(string uri, string name, string value) { throw null; }
public static System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues> ParseNullableQuery(string queryString) { throw null; }
public static System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues>? ParseNullableQuery(string queryString) { throw null; }
public static System.Collections.Generic.Dictionary<string, Microsoft.Extensions.Primitives.StringValues> ParseQuery(string queryString) { throw null; }
}
public static partial class ReasonPhrases

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System;
using System.IO;
@ -8,7 +10,7 @@ namespace Microsoft.AspNetCore.Internal
{
internal static class AspNetCoreTempDirectory
{
private static string _tempDirectory;
private static string? _tempDirectory;
public static string TempDirectory
{

View File

@ -23,12 +23,12 @@ namespace Microsoft.AspNetCore.WebUtilities
private readonly ArrayPool<byte> _bytePool;
private readonly int _memoryThreshold;
private readonly long? _bufferLimit;
private string _tempFileDirectory;
private readonly Func<string> _tempFileDirectoryAccessor;
private string _tempFileName;
private string? _tempFileDirectory;
private readonly Func<string>? _tempFileDirectoryAccessor;
private string? _tempFileName;
private Stream _buffer;
private byte[] _rentedBuffer;
private byte[]? _rentedBuffer;
private bool _inMemory = true;
private bool _completelyBuffered;
@ -137,7 +137,7 @@ namespace Microsoft.AspNetCore.WebUtilities
get { return _inMemory; }
}
public string TempFileName
public string? TempFileName
{
get { return _tempFileName; }
}

View File

@ -4,9 +4,8 @@
using System;
using System.Buffers;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Pipelines;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Internal;
@ -42,7 +41,7 @@ namespace Microsoft.AspNetCore.WebUtilities
public FileBufferingWriteStream(
int memoryThreshold = DefaultMemoryThreshold,
long? bufferLimit = null,
Func<string> tempFileDirectoryAccessor = null)
Func<string>? tempFileDirectoryAccessor = null)
{
if (memoryThreshold < 0)
{
@ -82,7 +81,7 @@ namespace Microsoft.AspNetCore.WebUtilities
internal PagedByteBuffer PagedByteBuffer { get; }
internal FileStream FileStream { get; private set; }
internal FileStream? FileStream { get; private set; }
internal bool Disposed { get; private set; }
@ -225,6 +224,7 @@ namespace Microsoft.AspNetCore.WebUtilities
}
}
[MemberNotNull(nameof(FileStream))]
private void EnsureFileStream()
{
if (FileStream == null)

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@ -29,9 +29,9 @@ namespace Microsoft.AspNetCore.WebUtilities
/// </summary>
/// <param name="section">The section from which to create the <see cref="FileMultipartSection"/></param>
/// <param name="header">An already parsed content disposition header</param>
public FileMultipartSection(MultipartSection section, ContentDispositionHeaderValue header)
public FileMultipartSection(MultipartSection section, ContentDispositionHeaderValue? header)
{
if (!header.IsFileDisposition())
if (header is null || !header.IsFileDisposition())
{
throw new ArgumentException($"Argument must be a file section", nameof(section));
}
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.WebUtilities
/// <summary>
/// Gets the file stream from the section body
/// </summary>
public Stream FileStream => Section.Body;
public Stream? FileStream => Section.Body;
/// <summary>
/// Gets the name of the section

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@ -29,7 +29,7 @@ namespace Microsoft.AspNetCore.WebUtilities
/// </summary>
/// <param name="section">The section from which to create the <see cref="FormMultipartSection"/></param>
/// <param name="header">An already parsed content disposition header</param>
public FormMultipartSection(MultipartSection section, ContentDispositionHeaderValue header)
public FormMultipartSection(MultipartSection section, ContentDispositionHeaderValue? header)
{
if (header == null || !header.IsFormDisposition())
{

View File

@ -34,8 +34,8 @@ namespace Microsoft.AspNetCore.WebUtilities
private static ReadOnlySpan<byte> UTF8AndEncoded => new byte[] { (byte)'&' };
// Used for other encodings
private byte[] _otherEqualEncoding;
private byte[] _otherAndEncoding;
private byte[]? _otherEqualEncoding;
private byte[]? _otherAndEncoding;
private readonly PipeReader _pipeReader;
private readonly Encoding _encoding;

View File

@ -4,6 +4,7 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
using System.Threading;
@ -28,8 +29,8 @@ namespace Microsoft.AspNetCore.WebUtilities
private readonly StringBuilder _builder = new StringBuilder();
private int _bufferOffset;
private int _bufferCount;
private string _currentKey;
private string _currentValue;
private string? _currentKey;
private string? _currentValue;
private bool _endOfStream;
private bool _disposed;
@ -189,7 +190,7 @@ namespace Microsoft.AspNetCore.WebUtilities
return true;
}
private bool TryReadWord(char separator, int limit, out string value)
private bool TryReadWord(char separator, int limit, [NotNullWhen(true)] out string? value)
{
do
{
@ -201,7 +202,7 @@ namespace Microsoft.AspNetCore.WebUtilities
return false;
}
private bool ReadChar(char separator, int limit, out string word)
private bool ReadChar(char separator, int limit, [NotNullWhen(true)] out string? word)
{
// End
if (_bufferCount == 0)
@ -283,6 +284,7 @@ namespace Microsoft.AspNetCore.WebUtilities
return accumulator.GetResults();
}
[MemberNotNullWhen(true, nameof(_currentKey), nameof(_currentValue))]
private bool ReadSucceeded()
{
return _currentKey != null && _currentValue != null;

View File

@ -328,14 +328,14 @@ namespace Microsoft.AspNetCore.WebUtilities
return charsRead;
}
public override async Task<string> ReadLineAsync()
public override async Task<string?> ReadLineAsync()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(HttpRequestStreamReader));
}
StringBuilder sb = null;
StringBuilder? sb = null;
var consumeLineFeed = false;
while (true)
@ -365,14 +365,14 @@ namespace Microsoft.AspNetCore.WebUtilities
// immediately followed by a line feed. The resulting string does not
// contain the terminating carriage return and/or line feed. The returned
// value is null if the end of the input stream has been reached.
public override string ReadLine()
public override string? ReadLine()
{
if (_disposed)
{
throw new ObjectDisposedException(nameof(HttpRequestStreamReader));
}
StringBuilder sb = null;
StringBuilder? sb = null;
var consumeLineFeed = false;
while (true)
@ -395,7 +395,7 @@ namespace Microsoft.AspNetCore.WebUtilities
}
}
private ReadLineStepResult ReadLineStep(ref StringBuilder sb, ref bool consumeLineFeed)
private ReadLineStepResult ReadLineStep(ref StringBuilder? sb, ref bool consumeLineFeed)
{
const char carriageReturn = '\r';
const char lineFeed = '\n';
@ -549,14 +549,14 @@ namespace Microsoft.AspNetCore.WebUtilities
public static ReadLineStepResult FromResult(string value) => new ReadLineStepResult(true, value);
private ReadLineStepResult(bool completed, string result)
private ReadLineStepResult(bool completed, string? result)
{
Completed = completed;
Result = result;
}
public bool Completed { get; }
public string Result { get; }
public string? Result { get; }
}
}
}

View File

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using System.Diagnostics;
using System.IO;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
@ -150,7 +151,7 @@ namespace Microsoft.AspNetCore.WebUtilities
};
}
public override void Write(string value)
public override void Write(string? value)
{
if (_disposed)
{
@ -257,21 +258,20 @@ namespace Microsoft.AspNetCore.WebUtilities
}
}
public override Task WriteAsync(string value)
public override Task WriteAsync(string? value)
{
if (_disposed)
{
return GetObjectDisposedTask();
}
var count = value?.Length ?? 0;
if (count == 0)
if (string.IsNullOrEmpty(value))
{
return Task.CompletedTask;
}
var remaining = _charBufferSize - _charBufferCount;
if (remaining >= count)
if (remaining >= value.Length)
{
// Enough room in buffer, no need to go async
CopyToCharBuffer(value);

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>ASP.NET Core utilities, such as for working with forms, multipart messages, and query strings.</Description>
@ -9,6 +9,8 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>aspnetcore</PackageTags>
<IsPackable>false</IsPackable>
<Nullable>enable</Nullable>
<LangVersion>Preview</LangVersion>
</PropertyGroup>
<ItemGroup>

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.WebUtilities
}
}
public byte[] BoundaryBytes { get; private set; }
public byte[] BoundaryBytes { get; private set; } = default!; // This gets initialized as part of Initialize called from in the ctor.
public int FinalBoundaryLength { get; private set; }
}

View File

@ -65,7 +65,7 @@ namespace Microsoft.AspNetCore.WebUtilities
/// </summary>
public long? BodyLengthLimit { get; set; }
public async Task<MultipartSection> ReadNextSectionAsync(CancellationToken cancellationToken = new CancellationToken())
public async Task<MultipartSection?> ReadNextSectionAsync(CancellationToken cancellationToken = new CancellationToken())
{
// Drain the prior section.
await _currentStream.DrainAsync(cancellationToken);
@ -115,4 +115,4 @@ namespace Microsoft.AspNetCore.WebUtilities
return accumulator.GetResults();
}
}
}
}

View File

@ -239,7 +239,7 @@ namespace Microsoft.AspNetCore.WebUtilities
return UpdatePosition(read);
}
var length = _boundary.BoundaryBytes.Length;
var length = _boundary.BoundaryBytes!.Length;
Debug.Assert(matchCount == length);
// "The boundary may be followed by zero or more characters of
@ -287,7 +287,7 @@ namespace Microsoft.AspNetCore.WebUtilities
matchOffset = segment1.Offset;
while (matchOffset < segmentEndMinusMatchBytesLength)
{
var lookaheadTailChar = segment1.Array[matchOffset + matchBytesLengthMinusOne];
var lookaheadTailChar = segment1.Array![matchOffset + matchBytesLengthMinusOne];
if (lookaheadTailChar == matchBytesLastByte &&
CompareBuffers(segment1.Array, matchOffset, matchBytes, 0, matchBytesLengthMinusOne) == 0)
{
@ -307,7 +307,7 @@ namespace Microsoft.AspNetCore.WebUtilities
var countLimit = segmentEnd - matchOffset;
for (matchCount = 0; matchCount < matchBytes.Length && matchCount < countLimit; matchCount++)
{
if (matchBytes[matchCount] != segment1.Array[matchOffset + matchCount])
if (matchBytes[matchCount] != segment1.Array![matchOffset + matchCount])
{
matchCount = 0;
break;

View File

@ -10,12 +10,11 @@ namespace Microsoft.AspNetCore.WebUtilities
{
public class MultipartSection
{
public string ContentType
public string? ContentType
{
get
{
StringValues values;
if (Headers.TryGetValue(HeaderNames.ContentType, out values))
if (Headers != null && Headers.TryGetValue(HeaderNames.ContentType, out var values))
{
return values;
}
@ -23,12 +22,11 @@ namespace Microsoft.AspNetCore.WebUtilities
}
}
public string ContentDisposition
public string? ContentDisposition
{
get
{
StringValues values;
if (Headers.TryGetValue(HeaderNames.ContentDisposition, out values))
if (Headers != null && Headers.TryGetValue(HeaderNames.ContentDisposition, out var values))
{
return values;
}
@ -36,9 +34,9 @@ namespace Microsoft.AspNetCore.WebUtilities
}
}
public Dictionary<string, StringValues> Headers { get; set; }
public Dictionary<string, StringValues>? Headers { get; set; }
public Stream Body { get; set; }
public Stream? Body { get; set; }
/// <summary>
/// The position where the body starts in the total multipart body.

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.WebUtilities
/// </summary>
/// <param name="section">The section to convert</param>
/// <returns>A file section</returns>
public static FileMultipartSection AsFileSection(this MultipartSection section)
public static FileMultipartSection? AsFileSection(this MultipartSection section)
{
if (section == null)
{
@ -38,7 +38,7 @@ namespace Microsoft.AspNetCore.WebUtilities
/// </summary>
/// <param name="section">The section to convert</param>
/// <returns>A form section</returns>
public static FormMultipartSection AsFormDataSection(this MultipartSection section)
public static FormMultipartSection? AsFormDataSection(this MultipartSection section)
{
if (section == null)
{
@ -60,10 +60,9 @@ namespace Microsoft.AspNetCore.WebUtilities
/// </summary>
/// <param name="section">The section from which to retrieve</param>
/// <returns>A <see cref="ContentDispositionHeaderValue"/> if the header was found, null otherwise</returns>
public static ContentDispositionHeaderValue GetContentDispositionHeader(this MultipartSection section)
public static ContentDispositionHeaderValue? GetContentDispositionHeader(this MultipartSection section)
{
ContentDispositionHeaderValue header;
if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out header))
if (!ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out var header))
{
return null;
}

View File

@ -1,4 +1,4 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
@ -26,10 +26,14 @@ namespace Microsoft.AspNetCore.WebUtilities
throw new ArgumentNullException(nameof(section));
}
MediaTypeHeaderValue sectionMediaType;
MediaTypeHeaderValue.TryParse(section.ContentType, out sectionMediaType);
if (section.Body is null)
{
throw new ArgumentException($"Multipart section must have a body to be read.", nameof(section));
}
Encoding streamEncoding = sectionMediaType?.Encoding;
MediaTypeHeaderValue.TryParse(section.ContentType, out var sectionMediaType);
var streamEncoding = sectionMediaType?.Encoding;
if (streamEncoding == null || streamEncoding == Encoding.UTF7)
{
streamEncoding = Encoding.UTF8;

View File

@ -15,7 +15,7 @@ namespace Microsoft.AspNetCore.WebUtilities
{
internal const int PageSize = 1024;
private readonly ArrayPool<byte> _arrayPool;
private byte[] _currentPage;
private byte[]? _currentPage;
private int _currentPageIndex;
public PagedByteBuffer(ArrayPool<byte> arrayPool)

View File

@ -43,7 +43,7 @@ namespace Microsoft.AspNetCore.WebUtilities
}
return AddQueryString(
uri, new[] { new KeyValuePair<string, string>(name, value) });
uri, new[] { new KeyValuePair<string, string?>(name, value) });
}
/// <summary>
@ -54,7 +54,7 @@ namespace Microsoft.AspNetCore.WebUtilities
/// <returns>The combined result.</returns>
/// <exception cref="ArgumentNullException"><paramref name="uri"/> is <c>null</c>.</exception>
/// <exception cref="ArgumentNullException"><paramref name="queryString"/> is <c>null</c>.</exception>
public static string AddQueryString(string uri, IDictionary<string, string> queryString)
public static string AddQueryString(string uri, IDictionary<string, string?> queryString)
{
if (uri == null)
{
@ -66,7 +66,7 @@ namespace Microsoft.AspNetCore.WebUtilities
throw new ArgumentNullException(nameof(queryString));
}
return AddQueryString(uri, (IEnumerable<KeyValuePair<string, string>>)queryString);
return AddQueryString(uri, (IEnumerable<KeyValuePair<string, string?>>)queryString);
}
/// <summary>
@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.WebUtilities
throw new ArgumentNullException(nameof(queryString));
}
return AddQueryString(uri, queryString.SelectMany(kvp => kvp.Value, (kvp, v) => KeyValuePair.Create(kvp.Key, v)));
return AddQueryString(uri, queryString.SelectMany(kvp => kvp.Value, (kvp, v) => KeyValuePair.Create<string, string?>(kvp.Key, v)));
}
/// <summary>
@ -102,7 +102,7 @@ namespace Microsoft.AspNetCore.WebUtilities
/// <exception cref="ArgumentNullException"><paramref name="queryString"/> is <c>null</c>.</exception>
public static string AddQueryString(
string uri,
IEnumerable<KeyValuePair<string, string>> queryString)
IEnumerable<KeyValuePair<string, string?>> queryString)
{
if (uri == null)
{
@ -169,7 +169,7 @@ namespace Microsoft.AspNetCore.WebUtilities
/// </summary>
/// <param name="queryString">The raw query string value, with or without the leading '?'.</param>
/// <returns>A collection of parsed keys and values, null if there are no entries.</returns>
public static Dictionary<string, StringValues> ParseNullableQuery(string queryString)
public static Dictionary<string, StringValues>? ParseNullableQuery(string queryString)
{
var accumulator = new KeyValueAccumulator();

View File

@ -80,8 +80,7 @@ namespace Microsoft.AspNetCore.WebUtilities
public static string GetReasonPhrase(int statusCode)
{
string phrase;
return Phrases.TryGetValue(statusCode, out phrase) ? phrase : string.Empty;
return Phrases.TryGetValue(statusCode, out var phrase) ? phrase : string.Empty;
}
}
}
}

View File

@ -89,7 +89,7 @@ namespace Microsoft.AspNetCore.WebUtilities
Assert.Equal(read0 + read1, stream.Position);
Assert.False(stream.InMemory);
Assert.NotNull(stream.TempFileName);
tempFileName = stream.TempFileName;
tempFileName = stream.TempFileName!;
Assert.True(File.Exists(tempFileName));
var read2 = stream.Read(bytes, 0, bytes.Length);
@ -150,7 +150,7 @@ namespace Microsoft.AspNetCore.WebUtilities
Assert.Equal(read0 + read1, stream.Position);
Assert.False(stream.InMemory);
Assert.NotNull(stream.TempFileName);
tempFileName = stream.TempFileName;
tempFileName = stream.TempFileName!;
Assert.True(File.Exists(tempFileName));
var exception = Assert.Throws<IOException>(() => stream.Read(bytes, 0, bytes.Length));
@ -219,7 +219,7 @@ namespace Microsoft.AspNetCore.WebUtilities
Assert.Equal(read0 + read1, stream.Position);
Assert.False(stream.InMemory);
Assert.NotNull(stream.TempFileName);
tempFileName = stream.TempFileName;
tempFileName = stream.TempFileName!;
Assert.True(File.Exists(tempFileName));
var read2 = await stream.ReadAsync(bytes, 0, bytes.Length);
@ -280,7 +280,7 @@ namespace Microsoft.AspNetCore.WebUtilities
Assert.Equal(read0 + read1, stream.Position);
Assert.False(stream.InMemory);
Assert.NotNull(stream.TempFileName);
tempFileName = stream.TempFileName;
tempFileName = stream.TempFileName!;
Assert.True(File.Exists(tempFileName));
var exception = await Assert.ThrowsAsync<IOException>(() => stream.ReadAsync(bytes, 0, bytes.Length));
@ -313,7 +313,7 @@ namespace Microsoft.AspNetCore.WebUtilities
stream.Read(new byte[4]);
Assert.True(File.Exists(stream.TempFileName), "tempFile should be created");
tempFileName = stream.TempFileName;
tempFileName = stream.TempFileName!;
arrayPool.Verify(v => v.Rent(It.IsAny<int>()), Times.Once());
arrayPool.Verify(v => v.Return(It.IsAny<byte[]>(), It.IsAny<bool>()), Times.Once());
@ -342,7 +342,7 @@ namespace Microsoft.AspNetCore.WebUtilities
await stream.ReadAsync(new byte[4]);
Assert.True(File.Exists(stream.TempFileName), "tempFile should be created");
tempFileName = stream.TempFileName;
tempFileName = stream.TempFileName!;
arrayPool.Verify(v => v.Rent(It.IsAny<int>()), Times.Once());
arrayPool.Verify(v => v.Return(It.IsAny<byte[]>(), It.IsAny<bool>()), Times.Once());

View File

@ -83,7 +83,7 @@ namespace Microsoft.AspNetCore.WebUtilities
// File should have been created.
Assert.NotNull(fileStream);
var fileBytes = ReadFileContent(fileStream);
var fileBytes = ReadFileContent(fileStream!);
Assert.Equal(input, fileBytes);
// No content should be in the memory stream
@ -106,7 +106,7 @@ namespace Microsoft.AspNetCore.WebUtilities
// File should have been created.
Assert.NotNull(fileStream);
var fileBytes = ReadFileContent(fileStream);
var fileBytes = ReadFileContent(fileStream!);
Assert.Equal(input, fileBytes);
// No content should be in the memory stream
@ -130,7 +130,7 @@ namespace Microsoft.AspNetCore.WebUtilities
// File should have been created.
Assert.NotNull(fileStream);
var fileBytes = ReadFileContent(fileStream);
var fileBytes = ReadFileContent(fileStream!);
Assert.Equal(new byte[] { 1, 2, 3, 4, 5, }, fileBytes);
Assert.Equal(new byte[] { 6, 7 }, ReadBufferedContent(pageBuffer));
@ -194,7 +194,7 @@ namespace Microsoft.AspNetCore.WebUtilities
// File should have been created.
Assert.NotNull(fileStream);
var fileBytes = ReadFileContent(fileStream);
var fileBytes = ReadFileContent(fileStream!);
Assert.Equal(input, fileBytes);
// No content should be in the memory stream
@ -217,7 +217,7 @@ namespace Microsoft.AspNetCore.WebUtilities
// File should have been created.
Assert.NotNull(fileStream);
var fileBytes = ReadFileContent(fileStream);
var fileBytes = ReadFileContent(fileStream!);
Assert.Equal(input, fileBytes);
// No content should be in the memory stream
@ -241,7 +241,7 @@ namespace Microsoft.AspNetCore.WebUtilities
// File should have been created.
Assert.NotNull(fileStream);
var fileBytes = ReadFileContent(fileStream);
var fileBytes = ReadFileContent(fileStream!);
Assert.Equal(input.Length, bufferingStream.Length);

View File

@ -214,7 +214,7 @@ namespace Microsoft.AspNetCore.WebUtilities
var readOnlySequence = new ReadOnlySequence<byte>(encoding.GetBytes("foo=bar&baz=boo"));
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
Assert.True(readOnlySequence.IsEmpty);
@ -233,7 +233,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
Assert.True(readOnlySequence.IsEmpty);
@ -252,7 +252,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.KeyLengthLimit = int.MaxValue;
formReader.ValueLengthLimit = int.MaxValue;
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: false);
@ -274,7 +274,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
Assert.True(readOnlySequence.IsEmpty);
@ -293,7 +293,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.KeyLengthLimit = int.MaxValue;
formReader.ValueLengthLimit = int.MaxValue;
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: false);
@ -315,7 +315,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
Assert.True(readOnlySequence.IsEmpty);
@ -333,7 +333,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
Assert.True(readOnlySequence.IsEmpty);
@ -352,7 +352,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
Assert.True(readOnlySequence.IsEmpty);
@ -371,7 +371,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null, encoding);
var formReader = new FormPipeReader(null!, encoding);
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
Assert.True(readOnlySequence.IsEmpty);
@ -388,7 +388,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null);
var formReader = new FormPipeReader(null!);
formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true);
Assert.True(readOnlySequence.IsEmpty);
@ -405,7 +405,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null);
var formReader = new FormPipeReader(null!);
formReader.KeyLengthLimit = 2;
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
@ -419,7 +419,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null);
var formReader = new FormPipeReader(null!);
formReader.KeyLengthLimit = 2;
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
@ -433,7 +433,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null);
var formReader = new FormPipeReader(null!);
formReader.ValueLengthLimit = 2;
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
@ -447,7 +447,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null);
var formReader = new FormPipeReader(null!);
formReader.ValueLengthLimit = 2;
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
@ -461,7 +461,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null);
var formReader = new FormPipeReader(null!);
formReader.KeyLengthLimit = 10;
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
@ -475,7 +475,7 @@ namespace Microsoft.AspNetCore.WebUtilities
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null);
var formReader = new FormPipeReader(null!);
formReader.ValueLengthLimit = 10;
var exception = Assert.Throws<InvalidDataException>(() => formReader.ParseFormValues(ref readOnlySequence, ref accumulator, isFinalBlock: true));
@ -506,7 +506,7 @@ namespace Microsoft.AspNetCore.WebUtilities
{
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null)
var formReader = new FormPipeReader(null!)
{
KeyLengthLimit = 3
};
@ -527,7 +527,7 @@ namespace Microsoft.AspNetCore.WebUtilities
{
KeyValueAccumulator accumulator = default;
var formReader = new FormPipeReader(null)
var formReader = new FormPipeReader(null!)
{
ValueLengthLimit = 3
};

View File

@ -443,12 +443,12 @@ namespace Microsoft.AspNetCore.WebUtilities
return new MemoryStream(data.ToArray());
}
public static IEnumerable<object[]> HttpRequestNullData()
public static IEnumerable<object?[]> HttpRequestNullData()
{
yield return new object[] { null, Encoding.UTF8, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object[] { new MemoryStream(), null, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object[] { new MemoryStream(), Encoding.UTF8, null, ArrayPool<char>.Shared };
yield return new object[] { new MemoryStream(), Encoding.UTF8, ArrayPool<byte>.Shared, null };
yield return new object?[] { null, Encoding.UTF8, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), null, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), Encoding.UTF8, null, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), Encoding.UTF8, ArrayPool<byte>.Shared, null };
}
public static IEnumerable<object[]> HttpRequestDisposeData()
@ -487,10 +487,10 @@ namespace Microsoft.AspNetCore.WebUtilities
public static IEnumerable<object[]> ReadLineData()
{
yield return new object[] { new Func<HttpRequestStreamReader, Task<string>>((httpRequestStreamReader) =>
yield return new object[] { new Func<HttpRequestStreamReader, Task<string?>>((httpRequestStreamReader) =>
Task.FromResult(httpRequestStreamReader.ReadLine())
)};
yield return new object[] { new Func<HttpRequestStreamReader, Task<string>>((httpRequestStreamReader) =>
yield return new object[] { new Func<HttpRequestStreamReader, Task<string?>>((httpRequestStreamReader) =>
httpRequestStreamReader.ReadLineAsync()
)};
}

View File

@ -679,12 +679,12 @@ namespace Microsoft.AspNetCore.WebUtilities
}
}
public static IEnumerable<object[]> HttpResponseStreamWriterData()
public static IEnumerable<object?[]> HttpResponseStreamWriterData()
{
yield return new object[] { null, Encoding.UTF8, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object[] { new MemoryStream(), null, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object[] { new MemoryStream(), Encoding.UTF8, null, ArrayPool<char>.Shared };
yield return new object[] { new MemoryStream(), Encoding.UTF8, ArrayPool<byte>.Shared, null };
yield return new object?[] { null, Encoding.UTF8, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), null, ArrayPool<byte>.Shared, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), Encoding.UTF8, null, ArrayPool<char>.Shared };
yield return new object?[] { new MemoryStream(), Encoding.UTF8, ArrayPool<byte>.Shared, null };
}
public static IEnumerable<object[]> HttpResponseDisposeData()

View File

@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable disable warnings
using System;
using System.IO;
using System.Text;

View File

@ -58,7 +58,7 @@ namespace Microsoft.AspNetCore.WebUtilities
[Fact]
public void AddQueryStringWithNullValueThrows()
{
Assert.Throws<ArgumentNullException>("value" ,() => QueryHelpers.AddQueryString("http://contoso.com/", "hello", null));
Assert.Throws<ArgumentNullException>("value" ,() => QueryHelpers.AddQueryString("http://contoso.com/", "hello", null!));
}
[Theory]
@ -109,7 +109,7 @@ namespace Microsoft.AspNetCore.WebUtilities
"http://contoso.com/someaction?hello=world&some=text&another=#name#something")]
public void AddQueryStringWithDictionary(string uri, string expectedUri)
{
var queryStrings = new Dictionary<string, string>()
var queryStrings = new Dictionary<string, string?>()
{
{ "hello", "world" },
{ "some", "text" },

View File

@ -37,7 +37,7 @@ namespace System.Buffers
if (_disposed)
return;
_array = null;
_array = null!;
_disposed = true;
}
}

View File

@ -2,6 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System.Collections.Generic;
using System.Text;
@ -112,8 +114,8 @@ namespace System.Buffers
int i = 0;
BufferSegment last = null;
BufferSegment first = null;
BufferSegment? last = null;
BufferSegment? first = null;
do
{
@ -137,7 +139,7 @@ namespace System.Buffers
}
else
{
last = last.Append(memory);
last = last!.Append(memory);
}
i++;
} while (i < inputs.Length);

View File

@ -1,6 +1,8 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
#nullable enable
using System;
#if NETCOREAPP
using System.Buffers;
@ -353,7 +355,7 @@ namespace Microsoft.Extensions.Internal
int bufferSize = GetArraySizeRequiredToEncode(input.Length);
char[] bufferToReturnToPool = null;
char[]? bufferToReturnToPool = null;
Span<char> buffer = bufferSize <= 128
? stackalloc char[bufferSize]
: bufferToReturnToPool = ArrayPool<char>.Shared.Rent(bufferSize);