diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index 9aef3d3e90ab99..ca336b55351fce 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -120,9 +120,6 @@ The maximum configured depth of {0} has been exceeded. Cannot read next JSON array. - - The JSON writer needs to be flushed before getting the current state. There are {0} bytes that have not been committed to the output. - Cannot read incomplete UTF-16 JSON text as string with missing low surrogate. @@ -620,12 +617,6 @@ Collection is read-only. - - Number was less than 0. - - - Destination array was not long enough. - A custom converter for JsonObject is not allowed on an extension property. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs index a6e6983e3c870c..d354200ccc13ef 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.MultiSegment.cs @@ -627,7 +627,7 @@ static int AmountToWrite(ReadOnlySpan span, long bytePositionInLine, ReadO _totalConsumed = prevTotalConsumed; consumed = default; _currentPosition = copy; - throw GetInvalidLiteralMultiSegment(readSoFar.Slice(0, written).ToArray()); + throw GetInvalidLiteralMultiSegment(readSoFar.Slice(0, written)); } private static int FindMismatch(ReadOnlySpan span, ReadOnlySpan literal) @@ -654,7 +654,7 @@ private static int FindMismatch(ReadOnlySpan span, ReadOnlySpan lite return indexOfFirstMismatch; } - private JsonException GetInvalidLiteralMultiSegment(ReadOnlySpan span) + private JsonException GetInvalidLiteralMultiSegment(scoped ReadOnlySpan span) { byte firstByte = span[0]; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs index eea091212e14d7..80ffc7426e7f58 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/Utf8JsonReader.cs @@ -1181,7 +1181,9 @@ private bool CheckLiteral(ReadOnlySpan span, ReadOnlySpan literal) return false; } - private void ThrowInvalidLiteral(ReadOnlySpan span) + private void ThrowInvalidLiteral(ReadOnlySpan span) => throw GetInvalidLiteral(span); + + private JsonException GetInvalidLiteral(ReadOnlySpan span) { byte firstByte = span[0]; @@ -1199,7 +1201,7 @@ private void ThrowInvalidLiteral(ReadOnlySpan span) resource = ExceptionResource.ExpectedNull; break; } - ThrowHelper.ThrowJsonReaderException(ref this, resource, bytes: span); + return ThrowHelper.GetJsonReaderException(ref this, resource, nextByte: default, bytes: span); } private bool ConsumeNumber() diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs index e6a7790d2b757b..899dcd46213557 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs @@ -54,12 +54,6 @@ public static void ThrowArgumentOutOfRangeException_CommentEnumMustBeInRange(str throw GetArgumentOutOfRangeException(parameterName, SR.CommentHandlingMustBeValid); } - [DoesNotReturn] - public static void ThrowArgumentOutOfRangeException_ArrayIndexNegative(string paramName) - { - throw new ArgumentOutOfRangeException(paramName, SR.ArrayIndexNegative); - } - [DoesNotReturn] public static void ThrowArgumentOutOfRangeException_JsonConverterFactory_TypeNotSupported(Type typeToConvert) { @@ -78,26 +72,15 @@ public static void ThrowArgumentException_InvalidOffLen() throw new ArgumentException(SR.Argument_InvalidOffLen); } - [DoesNotReturn] - public static void ThrowArgumentException_ArrayTooSmall(string paramName) - { - throw new ArgumentException(SR.ArrayTooSmall, paramName); - } - private static ArgumentException GetArgumentException(string message) { return new ArgumentException(message); } [DoesNotReturn] - public static void ThrowArgumentException(string message) + public static void ThrowArgumentException_ExpectedJsonTokens() { - throw GetArgumentException(message); - } - - public static InvalidOperationException GetInvalidOperationException_CallFlushFirst(int _buffered) - { - return GetInvalidOperationException(SR.Format(SR.CallFlushToAvoidDataLoss, _buffered)); + throw GetArgumentException(SR.ExpectedJsonTokens); } [DoesNotReturn] @@ -112,6 +95,10 @@ public static void ThrowArgumentException_PropertyNameTooLarge(int tokenLength) throw GetArgumentException(SR.Format(SR.PropertyNameTooLarge, tokenLength)); } + [DoesNotReturn] + public static void ThrowArgumentException_ValueTooLarge(int tokenLength) + => throw GetArgumentException(SR.Format(SR.ValueTooLarge, tokenLength)); + [DoesNotReturn] public static void ThrowArgumentException_ValueTooLarge(long tokenLength) { @@ -130,136 +117,11 @@ public static void ThrowInvalidOperationException_NeedLargerSpan() throw GetInvalidOperationException(SR.FailedToGetLargerSpan); } - [DoesNotReturn] - public static void ThrowPropertyNameTooLargeArgumentException(int length) - { - throw GetArgumentException(SR.Format(SR.PropertyNameTooLarge, length)); - } - - [DoesNotReturn] - public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadOnlySpan value) - { - if (propertyName.Length > JsonConstants.MaxUnescapedTokenSize) - { - ThrowArgumentException(SR.Format(SR.PropertyNameTooLarge, propertyName.Length)); - } - else - { - Debug.Assert(value.Length > JsonConstants.MaxUnescapedTokenSize); - ThrowArgumentException(SR.Format(SR.ValueTooLarge, value.Length)); - } - } - - [DoesNotReturn] - public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadOnlySpan value) - { - if (propertyName.Length > JsonConstants.MaxUnescapedTokenSize) - { - ThrowArgumentException(SR.Format(SR.PropertyNameTooLarge, propertyName.Length)); - } - else - { - Debug.Assert(value.Length > JsonConstants.MaxCharacterTokenSize); - ThrowArgumentException(SR.Format(SR.ValueTooLarge, value.Length)); - } - } - - [DoesNotReturn] - public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadOnlySpan value) - { - if (propertyName.Length > JsonConstants.MaxCharacterTokenSize) - { - ThrowArgumentException(SR.Format(SR.PropertyNameTooLarge, propertyName.Length)); - } - else - { - Debug.Assert(value.Length > JsonConstants.MaxUnescapedTokenSize); - ThrowArgumentException(SR.Format(SR.ValueTooLarge, value.Length)); - } - } - - [DoesNotReturn] - public static void ThrowArgumentException(ReadOnlySpan propertyName, ReadOnlySpan value) - { - if (propertyName.Length > JsonConstants.MaxCharacterTokenSize) - { - ThrowArgumentException(SR.Format(SR.PropertyNameTooLarge, propertyName.Length)); - } - else - { - Debug.Assert(value.Length > JsonConstants.MaxCharacterTokenSize); - ThrowArgumentException(SR.Format(SR.ValueTooLarge, value.Length)); - } - } - - [DoesNotReturn] - public static void ThrowInvalidOperationOrArgumentException(ReadOnlySpan propertyName, int currentDepth, int maxDepth) - { - currentDepth &= JsonConstants.RemoveFlagsBitMask; - if (currentDepth >= maxDepth) - { - ThrowInvalidOperationException(SR.Format(SR.DepthTooLarge, currentDepth, maxDepth)); - } - else - { - Debug.Assert(propertyName.Length > JsonConstants.MaxCharacterTokenSize); - ThrowArgumentException(SR.Format(SR.PropertyNameTooLarge, propertyName.Length)); - } - } - - [DoesNotReturn] - public static void ThrowInvalidOperationException(int currentDepth, int maxDepth) - { - currentDepth &= JsonConstants.RemoveFlagsBitMask; - Debug.Assert(currentDepth >= maxDepth); - ThrowInvalidOperationException(SR.Format(SR.DepthTooLarge, currentDepth, maxDepth)); - } - - [DoesNotReturn] - public static void ThrowInvalidOperationException(string message) - { - throw GetInvalidOperationException(message); - } - - private static InvalidOperationException GetInvalidOperationException(string message) + public static InvalidOperationException GetInvalidOperationException(string message) { return new InvalidOperationException(message) { Source = ExceptionSourceValueToRethrowAsJsonException }; } - [DoesNotReturn] - public static void ThrowInvalidOperationException_DepthNonZeroOrEmptyJson(int currentDepth) - { - throw GetInvalidOperationException(currentDepth); - } - - private static InvalidOperationException GetInvalidOperationException(int currentDepth) - { - currentDepth &= JsonConstants.RemoveFlagsBitMask; - if (currentDepth != 0) - { - return GetInvalidOperationException(SR.Format(SR.ZeroDepthAtEnd, currentDepth)); - } - else - { - return GetInvalidOperationException(SR.EmptyJsonIsInvalid); - } - } - - [DoesNotReturn] - public static void ThrowInvalidOperationOrArgumentException(ReadOnlySpan propertyName, int currentDepth, int maxDepth) - { - currentDepth &= JsonConstants.RemoveFlagsBitMask; - if (currentDepth >= maxDepth) - { - ThrowInvalidOperationException(SR.Format(SR.DepthTooLarge, currentDepth, maxDepth)); - } - else - { - Debug.Assert(propertyName.Length > JsonConstants.MaxCharacterTokenSize); - ThrowArgumentException(SR.Format(SR.PropertyNameTooLarge, propertyName.Length)); - } - } - public static InvalidOperationException GetInvalidOperationException_ExpectedArray(JsonTokenType tokenType) { return GetInvalidOperationException("array", tokenType); @@ -312,26 +174,6 @@ public static void ThrowInvalidOperationException_CannotSkipOnPartial() throw GetInvalidOperationException(SR.CannotSkip); } - [DoesNotReturn] - [MethodImpl(MethodImplOptions.NoInlining)] - public static void ThrowInvalidOperationException_CannotMixEncodings(EnclosingContainerType previousEncoding, EnclosingContainerType currentEncoding) - { - throw GetInvalidOperationException(SR.Format(SR.CannotMixEncodings, GetEncodingName(previousEncoding), GetEncodingName(currentEncoding))); - - static string GetEncodingName(EnclosingContainerType encoding) - { - switch (encoding) - { - case EnclosingContainerType.Utf8StringSequence: return "UTF-8"; - case EnclosingContainerType.Utf16StringSequence: return "UTF-16"; - case EnclosingContainerType.Base64StringSequence: return "Base64"; - default: - Debug.Fail("Unknown encoding."); - return "Unknown"; - }; - } - } - private static InvalidOperationException GetInvalidOperationException(string message, JsonTokenType tokenType) { return GetInvalidOperationException(SR.Format(SR.InvalidCast, tokenType, message)); @@ -367,13 +209,15 @@ internal static InvalidOperationException GetJsonElementWrongTypeException( } [DoesNotReturn] - public static void ThrowJsonReaderException(ref Utf8JsonReader json, ExceptionResource resource, byte nextByte = default, ReadOnlySpan bytes = default) - { - throw GetJsonReaderException(ref json, resource, nextByte, bytes); - } + public static void ThrowJsonReaderException(ref Utf8JsonReader json, ExceptionResource resource) + => throw GetJsonReaderException(ref json, resource, 0, default); + + [DoesNotReturn] + public static void ThrowJsonReaderException(ref Utf8JsonReader json, ExceptionResource resource, byte nextByte) + => throw GetJsonReaderException(ref json, resource, nextByte, default); [MethodImpl(MethodImplOptions.NoInlining)] - public static JsonException GetJsonReaderException(ref Utf8JsonReader json, ExceptionResource resource, byte nextByte, ReadOnlySpan bytes) + public static JsonException GetJsonReaderException(ref Utf8JsonReader json, ExceptionResource resource, byte nextByte, scoped ReadOnlySpan bytes) { string message = GetResourceString(ref json, resource, nextByte, JsonHelpers.Utf8GetString(bytes)); @@ -514,12 +358,6 @@ private static string GetResourceString(ref Utf8JsonReader json, ExceptionResour return message; } - [DoesNotReturn] - public static void ThrowInvalidOperationException(ExceptionResource resource, int currentDepth, int maxDepth, byte token, JsonTokenType tokenType) - { - throw GetInvalidOperationException(resource, currentDepth, maxDepth, token, tokenType); - } - [DoesNotReturn] public static void ThrowArgumentException_InvalidCommentValue() { @@ -528,6 +366,11 @@ public static void ThrowArgumentException_InvalidCommentValue() [DoesNotReturn] public static void ThrowArgumentException_InvalidUTF8(ReadOnlySpan value) + { + throw GetArgumentException_InvalidUTF8(value); + } + + private static ArgumentException GetArgumentException_InvalidUTF8(ReadOnlySpan value) { var builder = new StringBuilder(); @@ -551,7 +394,7 @@ public static void ThrowArgumentException_InvalidUTF8(ReadOnlySpan value) builder.Append("..."); } - throw new ArgumentException(SR.Format(SR.CannotEncodeInvalidUTF8, builder)); + return new ArgumentException(SR.Format(SR.CannotEncodeInvalidUTF8, builder)); } [DoesNotReturn] @@ -589,72 +432,21 @@ public static InvalidOperationException GetInvalidOperationException(string mess return ex; } - [MethodImpl(MethodImplOptions.NoInlining)] - public static InvalidOperationException GetInvalidOperationException(ExceptionResource resource, int currentDepth, int maxDepth, byte token, JsonTokenType tokenType) - { - string message = GetResourceString(resource, currentDepth, maxDepth, token, tokenType); - InvalidOperationException ex = GetInvalidOperationException(message); - ex.Source = ExceptionSourceValueToRethrowAsJsonException; - return ex; - } - [DoesNotReturn] public static void ThrowOutOfMemoryException(uint capacity) { throw new OutOfMemoryException(SR.Format(SR.BufferMaximumSizeExceeded, capacity)); } - // This function will convert an ExceptionResource enum value to the resource string. - [MethodImpl(MethodImplOptions.NoInlining)] - private static string GetResourceString(ExceptionResource resource, int currentDepth, int maxDepth, byte token, JsonTokenType tokenType) - { - string message = ""; - switch (resource) - { - case ExceptionResource.MismatchedObjectArray: - Debug.Assert(token == JsonConstants.CloseBracket || token == JsonConstants.CloseBrace); - message = (tokenType == JsonTokenType.PropertyName) ? - SR.Format(SR.CannotWriteEndAfterProperty, (char)token) : - SR.Format(SR.MismatchedObjectArray, (char)token); - break; - case ExceptionResource.DepthTooLarge: - message = SR.Format(SR.DepthTooLarge, currentDepth & JsonConstants.RemoveFlagsBitMask, maxDepth); - break; - case ExceptionResource.CannotStartObjectArrayWithoutProperty: - message = SR.Format(SR.CannotStartObjectArrayWithoutProperty, tokenType); - break; - case ExceptionResource.CannotStartObjectArrayAfterPrimitiveOrClose: - message = SR.Format(SR.CannotStartObjectArrayAfterPrimitiveOrClose, tokenType); - break; - case ExceptionResource.CannotWriteValueWithinObject: - message = SR.Format(SR.CannotWriteValueWithinObject, tokenType); - break; - case ExceptionResource.CannotWritePropertyWithinArray: - message = (tokenType == JsonTokenType.PropertyName) ? - SR.Format(SR.CannotWritePropertyAfterProperty) : - SR.Format(SR.CannotWritePropertyWithinArray, tokenType); - break; - case ExceptionResource.CannotWriteValueAfterPrimitiveOrClose: - message = SR.Format(SR.CannotWriteValueAfterPrimitiveOrClose, tokenType); - break; - case ExceptionResource.CannotWriteWithinString: - message = SR.CannotWriteWithinString; - break; - default: - Debug.Fail($"The ExceptionResource enum value: {resource} is not part of the switch. Add the appropriate case and exception message."); - break; - } - - return message; - } - [DoesNotReturn] public static void ThrowFormatException() { throw new FormatException { Source = ExceptionSourceValueToRethrowAsJsonException }; } - public static void ThrowFormatException(NumericType numericType) + public static void ThrowFormatException(NumericType numericType) => throw GetFormatException(numericType); + + private static FormatException GetFormatException(NumericType numericType) { string message = ""; @@ -707,11 +499,13 @@ public static void ThrowFormatException(NumericType numericType) break; } - throw new FormatException(message) { Source = ExceptionSourceValueToRethrowAsJsonException }; + return new FormatException(message) { Source = ExceptionSourceValueToRethrowAsJsonException }; } [DoesNotReturn] - public static void ThrowFormatException(DataType dataType) + public static void ThrowFormatException(DataType dataType) => throw GetFormatException(dataType); + + private static FormatException GetFormatException(DataType dataType) { string message = ""; @@ -735,7 +529,7 @@ public static void ThrowFormatException(DataType dataType) break; } - throw new FormatException(message) { Source = ExceptionSourceValueToRethrowAsJsonException }; + return new FormatException(message) { Source = ExceptionSourceValueToRethrowAsJsonException }; } [DoesNotReturn] @@ -791,12 +585,6 @@ internal enum ExceptionResource MismatchedObjectArray, ObjectDepthTooLarge, ZeroDepthAtEnd, - DepthTooLarge, - CannotStartObjectArrayWithoutProperty, - CannotStartObjectArrayAfterPrimitiveOrClose, - CannotWriteValueWithinObject, - CannotWriteValueAfterPrimitiveOrClose, - CannotWritePropertyWithinArray, ExpectedJsonTokens, TrailingCommaNotAllowedBeforeArrayEnd, TrailingCommaNotAllowedBeforeObjectEnd, @@ -806,7 +594,6 @@ internal enum ExceptionResource ExpectedOneCompleteToken, NotEnoughData, InvalidLeadingZeroInNumber, - CannotWriteWithinString, } internal enum NumericType diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs index 1ab10d31f53b21..4575ffda9186b2 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs @@ -107,48 +107,6 @@ public static void ValidateValue(ReadOnlySpan value) ThrowHelper.ThrowArgumentException_ValueTooLarge(value.Length); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ValidatePropertyAndValue(ReadOnlySpan propertyName, ReadOnlySpan value) - { - if (propertyName.Length > JsonConstants.MaxCharacterTokenSize || value.Length > JsonConstants.MaxUnescapedTokenSize) - ThrowHelper.ThrowArgumentException(propertyName, value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ValidatePropertyAndValue(ReadOnlySpan propertyName, ReadOnlySpan value) - { - if (propertyName.Length > JsonConstants.MaxUnescapedTokenSize || value.Length > JsonConstants.MaxCharacterTokenSize) - ThrowHelper.ThrowArgumentException(propertyName, value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ValidatePropertyAndValue(ReadOnlySpan propertyName, ReadOnlySpan value) - { - if (propertyName.Length > JsonConstants.MaxUnescapedTokenSize || value.Length > JsonConstants.MaxUnescapedTokenSize) - ThrowHelper.ThrowArgumentException(propertyName, value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ValidatePropertyAndValue(ReadOnlySpan propertyName, ReadOnlySpan value) - { - if (propertyName.Length > JsonConstants.MaxCharacterTokenSize || value.Length > JsonConstants.MaxCharacterTokenSize) - ThrowHelper.ThrowArgumentException(propertyName, value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ValidatePropertyNameLength(ReadOnlySpan propertyName) - { - if (propertyName.Length > JsonConstants.MaxCharacterTokenSize) - ThrowHelper.ThrowPropertyNameTooLargeArgumentException(propertyName.Length); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void ValidatePropertyNameLength(ReadOnlySpan propertyName) - { - if (propertyName.Length > JsonConstants.MaxUnescapedTokenSize) - ThrowHelper.ThrowPropertyNameTooLargeArgumentException(propertyName.Length); - } - internal static void ValidateNumber(ReadOnlySpan utf8FormattedNumber) { // This is a simplified version of the number reader from Utf8JsonReader.TryGetNumber, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs index cb087dd147c161..726326633e8a5e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Bytes.cs @@ -67,7 +67,7 @@ public void WriteBase64String(string propertyName, ReadOnlySpan bytes) /// public void WriteBase64String(ReadOnlySpan propertyName, ReadOnlySpan bytes) { - JsonWriterHelper.ValidatePropertyNameLength(propertyName); + JsonWriterHelper.ValidateProperty(propertyName); WriteBase64Escape(propertyName, bytes); @@ -91,7 +91,7 @@ public void WriteBase64String(ReadOnlySpan propertyName, ReadOnlySpan public void WriteBase64String(ReadOnlySpan utf8PropertyName, ReadOnlySpan bytes) { - JsonWriterHelper.ValidatePropertyNameLength(utf8PropertyName); + JsonWriterHelper.ValidateProperty(utf8PropertyName); WriteBase64Escape(utf8PropertyName, bytes); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Helpers.cs index 808255ae2a9687..b499acef1e84a3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.Helpers.cs @@ -11,25 +11,11 @@ namespace System.Text.Json { public sealed partial class Utf8JsonWriter { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ValidatePropertyNameAndDepth(ReadOnlySpan propertyName) - { - if (propertyName.Length > JsonConstants.MaxCharacterTokenSize || CurrentDepth >= _options.MaxDepth) - ThrowHelper.ThrowInvalidOperationOrArgumentException(propertyName, _currentDepth, _options.MaxDepth); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ValidatePropertyNameAndDepth(ReadOnlySpan utf8PropertyName) - { - if (utf8PropertyName.Length > JsonConstants.MaxUnescapedTokenSize || CurrentDepth >= _options.MaxDepth) - ThrowHelper.ThrowInvalidOperationOrArgumentException(utf8PropertyName, _currentDepth, _options.MaxDepth); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ValidateDepth() { if (CurrentDepth >= _options.MaxDepth) - ThrowHelper.ThrowInvalidOperationException(_currentDepth, _options.MaxDepth); + ThrowInvalidOperationException_DepthTooLarge(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -60,16 +46,16 @@ private void ValidateWritingProperty(byte token) } [DoesNotReturn] - [MethodImpl(MethodImplOptions.NoInlining)] private void OnValidateWritingPropertyFailed() { if (IsWritingPartialString) { - ThrowInvalidOperationException(ExceptionResource.CannotWriteWithinString); + ThrowInvalidOperationException_CannotWriteWithinString(); } Debug.Assert(_enclosingContainer != EnclosingContainerType.Object || _tokenType == JsonTokenType.PropertyName); - ThrowInvalidOperationException(ExceptionResource.CannotWritePropertyWithinArray); + throw ThrowHelper.GetInvalidOperationException( + _tokenType == JsonTokenType.PropertyName ? SR.CannotWritePropertyAfterProperty : SR.Format(SR.CannotWritePropertyWithinArray, _tokenType)); } private void WritePropertyNameMinimized(ReadOnlySpan escapedPropertyName, byte token) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs index ae8796a1be99b4..2cdcc45c5bdc50 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs @@ -509,7 +509,8 @@ public void WriteString(string propertyName, string? value) /// public void WriteString(ReadOnlySpan propertyName, ReadOnlySpan value) { - JsonWriterHelper.ValidatePropertyAndValue(propertyName, value); + JsonWriterHelper.ValidateProperty(propertyName); + JsonWriterHelper.ValidateValue(value); WriteStringEscape(propertyName, value); @@ -533,7 +534,8 @@ public void WriteString(ReadOnlySpan propertyName, ReadOnlySpan valu /// public void WriteString(ReadOnlySpan utf8PropertyName, ReadOnlySpan utf8Value) { - JsonWriterHelper.ValidatePropertyAndValue(utf8PropertyName, utf8Value); + JsonWriterHelper.ValidateProperty(utf8PropertyName); + JsonWriterHelper.ValidateValue(utf8Value); WriteStringEscape(utf8PropertyName, utf8Value); @@ -652,7 +654,8 @@ public void WriteString(string propertyName, ReadOnlySpan value) /// public void WriteString(ReadOnlySpan utf8PropertyName, ReadOnlySpan value) { - JsonWriterHelper.ValidatePropertyAndValue(utf8PropertyName, value); + JsonWriterHelper.ValidateProperty(utf8PropertyName); + JsonWriterHelper.ValidateValue(value); WriteStringEscape(utf8PropertyName, value); @@ -739,7 +742,8 @@ public void WriteString(string propertyName, ReadOnlySpan utf8Value) /// public void WriteString(ReadOnlySpan propertyName, ReadOnlySpan utf8Value) { - JsonWriterHelper.ValidatePropertyAndValue(propertyName, utf8Value); + JsonWriterHelper.ValidateProperty(propertyName); + JsonWriterHelper.ValidateValue(utf8Value); WriteStringEscape(propertyName, utf8Value); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs index 1a450b476919c0..a0d37f7e1a943b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Helpers.cs @@ -48,30 +48,36 @@ private void ValidateWritingValue() } [DoesNotReturn] - [MethodImpl(MethodImplOptions.NoInlining)] private void OnValidateWritingValueFailed() { Debug.Assert(!_options.SkipValidation); if (IsWritingPartialString) { - ThrowInvalidOperationException(ExceptionResource.CannotWriteWithinString); + ThrowInvalidOperationException_CannotWriteWithinString(); } + throw GetValidateWritingValueFailedException(); + } + + private InvalidOperationException GetValidateWritingValueFailedException() + { Debug.Assert(!HasPartialStringData); + string message; if (_enclosingContainer == EnclosingContainerType.Object) { Debug.Assert(_tokenType != JsonTokenType.PropertyName); Debug.Assert(_tokenType != JsonTokenType.None && _tokenType != JsonTokenType.StartArray); - ThrowInvalidOperationException(ExceptionResource.CannotWriteValueWithinObject); + message = SR.CannotWriteValueWithinObject; } else { Debug.Assert(_tokenType != JsonTokenType.PropertyName); Debug.Assert(CurrentDepth == 0 && _tokenType != JsonTokenType.None); - ThrowInvalidOperationException(ExceptionResource.CannotWriteValueAfterPrimitiveOrClose); + message = SR.CannotWriteValueAfterPrimitiveOrClose; } + return ThrowHelper.GetInvalidOperationException(SR.Format(message, _tokenType)); } private void ValidateWritingSegment(EnclosingContainerType currentSegmentEncoding) @@ -90,35 +96,37 @@ private void ValidateWritingSegment(EnclosingContainerType currentSegmentEncodin } [DoesNotReturn] - [MethodImpl(MethodImplOptions.NoInlining)] private void OnValidateWritingSegmentFailed(EnclosingContainerType currentSegmentEncoding) + => throw GetValidateWritingSegmentFailedException(currentSegmentEncoding); + + private InvalidOperationException GetValidateWritingSegmentFailedException(EnclosingContainerType currentSegmentEncoding) { if (IsWritingPartialString) { - ThrowHelper.ThrowInvalidOperationException_CannotMixEncodings(_enclosingContainer, currentSegmentEncoding); + return ThrowHelper.GetInvalidOperationException(SR.Format(SR.CannotMixEncodings, GetEncodingName(_enclosingContainer), GetEncodingName(currentSegmentEncoding))); + + static string GetEncodingName(EnclosingContainerType encoding) + { + switch (encoding) + { + case EnclosingContainerType.Utf8StringSequence: return "UTF-8"; + case EnclosingContainerType.Utf16StringSequence: return "UTF-16"; + case EnclosingContainerType.Base64StringSequence: return "Base64"; + default: + Debug.Fail("Unknown encoding."); + return "Unknown"; + } + } } - Debug.Assert(!HasPartialStringData); - - if (_enclosingContainer == EnclosingContainerType.Object) - { - Debug.Assert(_tokenType != JsonTokenType.PropertyName); - Debug.Assert(_tokenType != JsonTokenType.None && _tokenType != JsonTokenType.StartArray); - ThrowInvalidOperationException(ExceptionResource.CannotWriteValueWithinObject); - } - else - { - Debug.Assert(_tokenType != JsonTokenType.PropertyName); - Debug.Assert(CurrentDepth == 0 && _tokenType != JsonTokenType.None); - ThrowInvalidOperationException(ExceptionResource.CannotWriteValueAfterPrimitiveOrClose); - } + return GetValidateWritingValueFailedException(); } private void ValidateNotWithinUnfinalizedString() { if (IsWritingPartialString) { - ThrowInvalidOperationException(ExceptionResource.CannotWriteWithinString); + ThrowInvalidOperationException_CannotWriteWithinString(); } Debug.Assert(!HasPartialStringData); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs index 9c1bb2a99f077d..ff0e6a4c8558d9 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Raw.cs @@ -142,7 +142,7 @@ public void WriteRawValue(ReadOnlySequence utf8Json, bool skipInputValidat if (utf8JsonLen == 0) { - ThrowHelper.ThrowArgumentException(SR.ExpectedJsonTokens); + ThrowHelper.ThrowArgumentException_ExpectedJsonTokens(); } if (utf8JsonLen >= int.MaxValue) { @@ -231,7 +231,7 @@ private void WriteRawValueCore(ReadOnlySpan utf8Json, bool skipInputValida if (len == 0) { - ThrowHelper.ThrowArgumentException(SR.ExpectedJsonTokens); + ThrowHelper.ThrowArgumentException_ExpectedJsonTokens(); } // In the UTF-16-based entry point methods above, we validate that the payload length <= int.MaxValue /3. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs index 6409daf43381d0..b86c2a7dcae10a 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.cs @@ -633,32 +633,41 @@ private void ValidateStart() } [DoesNotReturn] - [MethodImpl(MethodImplOptions.NoInlining)] private void OnValidateStartFailed() { // Make sure a new object or array is not attempted within an unfinalized string. if (IsWritingPartialString) { - ThrowInvalidOperationException(ExceptionResource.CannotWriteWithinString); + ThrowInvalidOperationException_CannotWriteWithinString(); } + throw GetValidateStartFailedException(); + } + + private InvalidOperationException GetValidateStartFailedException() + { Debug.Assert(!HasPartialStringData); + string message; if (_enclosingContainer == EnclosingContainerType.Object) { Debug.Assert(_tokenType != JsonTokenType.PropertyName); Debug.Assert(_tokenType != JsonTokenType.None && _tokenType != JsonTokenType.StartArray); - ThrowInvalidOperationException(ExceptionResource.CannotStartObjectArrayWithoutProperty); + message = SR.CannotStartObjectArrayWithoutProperty; } else { Debug.Assert(_tokenType != JsonTokenType.PropertyName); Debug.Assert(_tokenType != JsonTokenType.StartObject); Debug.Assert(CurrentDepth == 0 && _tokenType != JsonTokenType.None); - ThrowInvalidOperationException(ExceptionResource.CannotStartObjectArrayAfterPrimitiveOrClose); + message = SR.CannotStartObjectArrayAfterPrimitiveOrClose; } + return ThrowHelper.GetInvalidOperationException(SR.Format(message, _tokenType)); } + private static void ThrowInvalidOperationException_CannotWriteWithinString() + => throw ThrowHelper.GetInvalidOperationException(SR.CannotWriteWithinString); + private void WriteStartIndented(byte token) { int indent = Indentation; @@ -745,7 +754,8 @@ private void WriteStartHelper(ReadOnlySpan utf8PropertyName, byte token) /// public void WriteStartArray(ReadOnlySpan utf8PropertyName) { - ValidatePropertyNameAndDepth(utf8PropertyName); + JsonWriterHelper.ValidateProperty(utf8PropertyName); + ValidateDepth(); WriteStartEscape(utf8PropertyName, JsonConstants.OpenBracket); @@ -770,7 +780,8 @@ public void WriteStartArray(ReadOnlySpan utf8PropertyName) /// public void WriteStartObject(ReadOnlySpan utf8PropertyName) { - ValidatePropertyNameAndDepth(utf8PropertyName); + JsonWriterHelper.ValidateProperty(utf8PropertyName); + ValidateDepth(); WriteStartEscape(utf8PropertyName, JsonConstants.OpenBrace); @@ -894,7 +905,8 @@ public void WriteStartObject(string propertyName) /// public void WriteStartArray(ReadOnlySpan propertyName) { - ValidatePropertyNameAndDepth(propertyName); + JsonWriterHelper.ValidateProperty(propertyName); + ValidateDepth(); WriteStartEscape(propertyName, JsonConstants.OpenBracket); @@ -919,7 +931,8 @@ public void WriteStartArray(ReadOnlySpan propertyName) /// public void WriteStartObject(ReadOnlySpan propertyName) { - ValidatePropertyNameAndDepth(propertyName); + JsonWriterHelper.ValidateProperty(propertyName); + ValidateDepth(); WriteStartEscape(propertyName, JsonConstants.OpenBrace); @@ -1228,20 +1241,17 @@ private void SetFlagToAddListSeparatorBeforeNextItem() _currentDepth |= 1 << 31; } - [MethodImpl(MethodImplOptions.NoInlining)] - [DoesNotReturn] - private void ThrowInvalidOperationException(ExceptionResource resource) - => ThrowHelper.ThrowInvalidOperationException(resource, currentDepth: default, maxDepth: _options.MaxDepth, token: default, _tokenType); - - [MethodImpl(MethodImplOptions.NoInlining)] [DoesNotReturn] private void ThrowInvalidOperationException_MismatchedObjectArray(byte token) - => ThrowHelper.ThrowInvalidOperationException(ExceptionResource.MismatchedObjectArray, currentDepth: default, maxDepth: _options.MaxDepth, token, _tokenType); + { + Debug.Assert(token is JsonConstants.CloseBracket or JsonConstants.CloseBrace); + throw ThrowHelper.GetInvalidOperationException( + SR.Format(_tokenType == JsonTokenType.PropertyName ? SR.CannotWriteEndAfterProperty : SR.MismatchedObjectArray, (char)token)); + } - [MethodImpl(MethodImplOptions.NoInlining)] [DoesNotReturn] private void ThrowInvalidOperationException_DepthTooLarge() - => ThrowHelper.ThrowInvalidOperationException(ExceptionResource.DepthTooLarge, _currentDepth, _options.MaxDepth, token: default, tokenType: default); + => throw ThrowHelper.GetInvalidOperationException(SR.Format(SR.DepthTooLarge, CurrentDepth, _options.MaxDepth)); [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay => $"BytesCommitted = {BytesCommitted} BytesPending = {BytesPending} CurrentDepth = {CurrentDepth}";