< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 64
Coverable lines: 64
Total lines: 147
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 22
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
Read(...)0%440%
ReadCore(...)0%14140%
IsWhiteSpaceByte(...)0%220%
Write(...)0%220%
ReadAsPropertyNameCore(...)100%110%
WriteAsPropertyNameCore(...)100%110%
GetSchema(...)100%110%
GetSupportedJsonValueTypes(...)100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/VersionConverter.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Buffers;
 5using System.Diagnostics;
 6using System.Text.Json.Nodes;
 7using System.Text.Json.Schema;
 8
 9namespace System.Text.Json.Serialization.Converters
 10{
 11    internal sealed class VersionConverter : JsonPrimitiveConverter<Version?>
 12    {
 13#if NET
 14        private const int MaximumFormattedVersionLength = 43; // 2147483647.2147483647.2147483647.2147483647
 15#endif
 16
 17        public override Version? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
 018        {
 019            if (reader.TokenType is JsonTokenType.Null)
 020            {
 021                return null;
 22            }
 23
 024            if (reader.TokenType != JsonTokenType.String)
 025            {
 026                ThrowHelper.ThrowInvalidOperationException_ExpectedString(reader.TokenType);
 27            }
 28
 029            return ReadCore(ref reader);
 030        }
 31
 32        private static unsafe Version ReadCore(ref Utf8JsonReader reader)
 033        {
 034            Debug.Assert(reader.TokenType is JsonTokenType.PropertyName or JsonTokenType.String);
 35
 36#if NET
 037            int bufferLength = reader.ValueLength;
 038            byte[]? rentedBuffer = null;
 39            try
 040            {
 041                Span<byte> utf8Buffer = bufferLength <= JsonConstants.StackallocByteThreshold
 042                    ? stackalloc byte[JsonConstants.StackallocByteThreshold]
 043                    : (rentedBuffer = ArrayPool<byte>.Shared.Rent(bufferLength));
 44
 045                int bytesWritten = reader.CopyString(utf8Buffer);
 046                ReadOnlySpan<byte> utf8Source = utf8Buffer.Slice(0, bytesWritten);
 47
 48                // Since leading and trailing whitespaces are forbidden throughout System.Text.Json converters
 49                // we need to make sure that our input doesn't have them,
 50                // and if it has - we need to throw, to match behaviour of other converters
 51                // since Version.TryParse allows them and silently parses input to Version
 052                if (utf8Source.IsEmpty || IsWhiteSpaceByte(utf8Source[0]) || IsWhiteSpaceByte(utf8Source[^1]))
 053                {
 054                    ThrowHelper.ThrowFormatException(DataType.Version);
 55                }
 56
 057                if (Version.TryParse(utf8Source, out Version? result))
 058                {
 059                    return result!;
 60                }
 061            }
 62            finally
 063            {
 064                if (rentedBuffer is not null)
 065                {
 066                    ArrayPool<byte>.Shared.Return(rentedBuffer);
 067                }
 068            }
 69#else
 70            string? versionString = reader.GetString();
 71            if (string.IsNullOrEmpty(versionString) || char.IsWhiteSpace(versionString[0]) || char.IsWhiteSpace(versionS
 72            {
 73                // Since leading and trailing whitespaces are forbidden throughout System.Text.Json converters
 74                // we need to make sure that our input doesn't have them,
 75                // and if it has - we need to throw, to match behaviour of other converters
 76                // since Version.TryParse allows them and silently parses input to Version
 77                ThrowHelper.ThrowFormatException(DataType.Version);
 78            }
 79
 80            if (Version.TryParse(versionString, out Version? result))
 81            {
 82                return result;
 83            }
 84#endif
 085            ThrowHelper.ThrowJsonException();
 86            return null;
 087        }
 88
 89#if NET
 90        private static bool IsWhiteSpaceByte(byte b)
 091        {
 92            // Check for ASCII whitespace characters: space (0x20), tab (0x09), newline (0x0A),
 93            // carriage return (0x0D), form feed (0x0C), and vertical tab (0x0B)
 94            // For non-ASCII bytes, convert to char and check with char.IsWhiteSpace
 095            return b <= 127 ? char.IsWhiteSpace((char)b) : false;
 096        }
 97#endif
 98
 99        public override unsafe void Write(Utf8JsonWriter writer, Version? value, JsonSerializerOptions options)
 0100        {
 0101            if (value is null)
 0102            {
 0103                writer.WriteNullValue();
 0104                return;
 105            }
 106
 107#if NET
 0108            Span<byte> span = stackalloc byte[MaximumFormattedVersionLength];
 0109            bool formattedSuccessfully = value.TryFormat(span, out int charsWritten);
 0110            Debug.Assert(formattedSuccessfully);
 0111            writer.WriteStringValue(span.Slice(0, charsWritten));
 112#else
 113            writer.WriteStringValue(value.ToString());
 114#endif
 0115        }
 116
 117        internal override Version ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOp
 0118        {
 0119            return ReadCore(ref reader);
 0120        }
 121
 122        internal override unsafe void WriteAsPropertyNameCore(Utf8JsonWriter writer, Version value, JsonSerializerOption
 0123        {
 0124            ArgumentNullException.ThrowIfNull(value);
 125
 126#if NET
 0127            Span<byte> span = stackalloc byte[MaximumFormattedVersionLength];
 0128            bool formattedSuccessfully = value.TryFormat(span, out int charsWritten);
 0129            Debug.Assert(formattedSuccessfully);
 0130            writer.WritePropertyName(span.Slice(0, charsWritten));
 131#else
 132            writer.WritePropertyName(value.ToString());
 133#endif
 0134        }
 135
 136        internal override JsonSchema? GetSchema(JsonNumberHandling _) =>
 0137            new()
 0138            {
 0139                Type = JsonSchemaType.String,
 0140                Comment = "Represents a version string.",
 0141                Pattern = @"^\d+(\.\d+){1,3}$",
 0142            };
 143
 0144        internal override JsonValueType GetSupportedJsonValueTypes(JsonNumberHandling _) => JsonValueType.String;
 145    }
 146}
 147