private DateOnly ReadCore(ref Utf8JsonReader reader) { bool isEscaped = reader._stringHasEscaping; ReadOnlySpan <byte> source = stackalloc byte[0]; if (reader.HasValueSequence) { ReadOnlySequence <byte> valueSequence = reader.ValueSequence; long sequenceLength = valueSequence.Length; if (!JsonHelpers.IsInRangeInclusive(sequenceLength, FormatLength, MaxEscapedFormatLength)) { ThrowHelper.ThrowFormatException(DataType.DateOnly); } Span <byte> stackSpan = stackalloc byte[isEscaped ? FormatLength : MaxEscapedFormatLength]; valueSequence.CopyTo(stackSpan); source = stackSpan.Slice(0, (int)sequenceLength); } else { source = reader.ValueSpan; if (!JsonHelpers.IsInRangeInclusive(source.Length, FormatLength, MaxEscapedFormatLength)) { ThrowHelper.ThrowFormatException(DataType.DateOnly); } } if (isEscaped) { int backslash = source.IndexOf(JsonConstants.BackSlash); Debug.Assert(backslash != -1); Span <byte> sourceUnescaped = stackalloc byte[MaxEscapedFormatLength]; JsonReaderHelper.Unescape(source, sourceUnescaped, backslash, out int written); Debug.Assert(written > 0); source = sourceUnescaped.Slice(0, written); Debug.Assert(!source.IsEmpty); } if (!JsonHelpers.TryParseAsIso(source, out DateOnly value)) { ThrowHelper.ThrowFormatException(DataType.DateOnly); } return(value); }
public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.String) { ThrowHelper.ThrowInvalidOperationException_ExpectedString(reader.TokenType); } #if BUILDING_INBOX_LIBRARY bool isEscaped = reader._stringHasEscaping; int maxLength = isEscaped ? MaximumEscapedVersionLength : MaximumVersionLength; ReadOnlySpan <byte> source = stackalloc byte[0]; if (reader.HasValueSequence) { if (!JsonHelpers.IsInRangeInclusive(reader.ValueSequence.Length, MinimumVersionLength, maxLength)) { ThrowHelper.ThrowFormatException(DataType.Version); } Span <byte> stackSpan = stackalloc byte[isEscaped ? MaximumEscapedVersionLength : MaximumVersionLength]; reader.ValueSequence.CopyTo(stackSpan); source = stackSpan.Slice(0, (int)reader.ValueSequence.Length); } else { source = reader.ValueSpan; if (!JsonHelpers.IsInRangeInclusive(source.Length, MinimumVersionLength, maxLength)) { ThrowHelper.ThrowFormatException(DataType.Version); } } if (isEscaped) { int backslash = source.IndexOf(JsonConstants.BackSlash); Debug.Assert(backslash != -1); Span <byte> sourceUnescaped = stackalloc byte[MaximumEscapedVersionLength]; JsonReaderHelper.Unescape(source, sourceUnescaped, backslash, out int written); Debug.Assert(written > 0); source = sourceUnescaped.Slice(0, written); Debug.Assert(!source.IsEmpty); } byte firstChar = source[0]; byte lastChar = source[source.Length - 1]; if (!JsonHelpers.IsDigit(firstChar) || !JsonHelpers.IsDigit(lastChar)) { // Since leading and trailing whitespaces are forbidden throughout System.Text.Json converters // we need to make sure that our input doesn't have them, // and if it has - we need to throw, to match behaviour of other converters // since Version.TryParse allows them and silently parses input to Version ThrowHelper.ThrowFormatException(DataType.Version); } Span <char> charBuffer = stackalloc char[MaximumVersionLength]; int writtenChars = JsonReaderHelper.s_utf8Encoding.GetChars(source, charBuffer); if (Version.TryParse(charBuffer.Slice(0, writtenChars), out Version? result)) { return(result); } #else string?versionString = reader.GetString(); if (!string.IsNullOrEmpty(versionString) && (!char.IsDigit(versionString[0]) || !char.IsDigit(versionString[versionString.Length - 1]))) { // Since leading and trailing whitespaces are forbidden throughout System.Text.Json converters // we need to make sure that our input doesn't have them, // and if it has - we need to throw, to match behaviour of other converters // since Version.TryParse allows them and silently parses input to Version ThrowHelper.ThrowFormatException(DataType.Version); } if (Version.TryParse(versionString, out Version? result)) { return(result); } #endif ThrowHelper.ThrowJsonException(); return(null); }
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType != JsonTokenType.String) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(reader.TokenType); } bool isEscaped = reader._stringHasEscaping; int maximumLength = isEscaped ? MaximumEscapedTimeSpanFormatLength : MaximumTimeSpanFormatLength; ReadOnlySpan <byte> source = stackalloc byte[0]; if (reader.HasValueSequence) { ReadOnlySequence <byte> valueSequence = reader.ValueSequence; long sequenceLength = valueSequence.Length; if (!JsonHelpers.IsInRangeInclusive(sequenceLength, MinimumTimeSpanFormatLength, maximumLength)) { throw ThrowHelper.GetFormatException(DataType.TimeSpan); } Span <byte> stackSpan = stackalloc byte[isEscaped ? MaximumEscapedTimeSpanFormatLength : MaximumTimeSpanFormatLength]; valueSequence.CopyTo(stackSpan); source = stackSpan.Slice(0, (int)sequenceLength); } else { source = reader.ValueSpan; if (!JsonHelpers.IsInRangeInclusive(source.Length, MinimumTimeSpanFormatLength, maximumLength)) { throw ThrowHelper.GetFormatException(DataType.TimeSpan); } } if (isEscaped) { int backslash = source.IndexOf(JsonConstants.BackSlash); Debug.Assert(backslash != -1); Span <byte> sourceUnescaped = stackalloc byte[MaximumEscapedTimeSpanFormatLength]; JsonReaderHelper.Unescape(source, sourceUnescaped, backslash, out int written); Debug.Assert(written > 0); source = sourceUnescaped.Slice(0, written); Debug.Assert(!source.IsEmpty); } byte firstChar = source[0]; if (!JsonHelpers.IsDigit(firstChar) && firstChar != '-') { // Note: Utf8Parser.TryParse allows for leading whitespace so we // need to exclude that case here. throw ThrowHelper.GetFormatException(DataType.TimeSpan); } bool result = Utf8Parser.TryParse(source, out TimeSpan tmpValue, out int bytesConsumed, 'c'); // Note: Utf8Parser.TryParse will return true for invalid input so // long as it starts with an integer. Example: "2021-06-18" or // "1$$$$$$$$$$". We need to check bytesConsumed to know if the // entire source was actually valid. if (result && source.Length == bytesConsumed) { return(tmpValue); } throw ThrowHelper.GetFormatException(DataType.TimeSpan); }