< Summary

Information
Class: System.Net.Http.Headers.ViaHeaderValue
Assembly: System.Net.Http
File(s): D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\Headers\ViaHeaderValue.cs
Line coverage
68%
Covered lines: 111
Uncovered lines: 50
Coverable lines: 161
Total lines: 268
Line coverage: 68.9%
Branch coverage
68%
Covered branches: 33
Total branches: 48
Branch coverage: 68.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%11100%
.ctor(...)100%110%
.ctor(...)100%110%
.ctor(...)100%44100%
.ctor(...)100%110%
ToString()100%44100%
Equals(...)0%880%
GetHashCode()0%220%
Parse(...)100%110%
TryParse(...)0%220%
GetViaLength(...)87.5%161693.54%
GetProtocolEndIndex(...)100%1010100%
System.ICloneable.Clone()100%110%
CheckReceivedBy(...)50%2266.66%

File(s)

D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\Headers\ViaHeaderValue.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.Diagnostics;
 5using System.Diagnostics.CodeAnalysis;
 6using System.Text;
 7
 8namespace System.Net.Http.Headers
 9{
 10    public class ViaHeaderValue : ICloneable
 11    {
 12        private readonly string? _protocolName;
 13        private readonly string _protocolVersion;
 14        private readonly string _receivedBy;
 15        private readonly string? _comment;
 16
 017        public string? ProtocolName => _protocolName;
 18
 019        public string ProtocolVersion => _protocolVersion;
 20
 021        public string ReceivedBy => _receivedBy;
 22
 023        public string? Comment => _comment;
 24
 2724825        private ViaHeaderValue(string protocolVersion, string receivedBy, string? protocolName, string? comment, bool _)
 2724826        {
 27#if DEBUG
 28            // This constructor should only be used with already validated values.
 2724829            new ViaHeaderValue(protocolVersion, receivedBy, protocolName, comment);
 30#endif
 31
 2724832            _protocolVersion = protocolVersion;
 2724833            _receivedBy = receivedBy;
 2724834            _protocolName = protocolName;
 2724835            _comment = comment;
 2724836        }
 37
 38        public ViaHeaderValue(string protocolVersion, string receivedBy)
 039            : this(protocolVersion, receivedBy, null, null)
 040        {
 041        }
 42
 43        public ViaHeaderValue(string protocolVersion, string receivedBy, string? protocolName)
 044            : this(protocolVersion, receivedBy, protocolName, null)
 045        {
 046        }
 47
 2724848        public ViaHeaderValue(string protocolVersion, string receivedBy, string? protocolName, string? comment)
 2724849        {
 2724850            HeaderUtilities.CheckValidToken(protocolVersion);
 2724851            CheckReceivedBy(receivedBy);
 52
 2724853            if (!string.IsNullOrEmpty(protocolName))
 4854            {
 4855                HeaderUtilities.CheckValidToken(protocolName);
 4856                _protocolName = protocolName;
 4857            }
 58
 2724859            if (!string.IsNullOrEmpty(comment))
 14660            {
 14661                HeaderUtilities.CheckValidComment(comment);
 14662                _comment = comment;
 14663            }
 64
 2724865            _protocolVersion = protocolVersion;
 2724866            _receivedBy = receivedBy;
 2724867        }
 68
 069        private ViaHeaderValue(ViaHeaderValue source)
 070        {
 071            Debug.Assert(source != null);
 72
 073            _protocolName = source._protocolName;
 074            _protocolVersion = source._protocolVersion;
 075            _receivedBy = source._receivedBy;
 076            _comment = source._comment;
 077        }
 78
 79        public override string ToString()
 4458080        {
 4458081            var sb = new ValueStringBuilder(stackalloc char[256]);
 82
 4458083            if (!string.IsNullOrEmpty(_protocolName))
 8084            {
 8085                sb.Append(_protocolName);
 8086                sb.Append('/');
 8087            }
 88
 4458089            sb.Append(_protocolVersion);
 4458090            sb.Append(' ');
 4458091            sb.Append(_receivedBy);
 92
 4458093            if (!string.IsNullOrEmpty(_comment))
 13094            {
 13095                sb.Append(' ');
 13096                sb.Append(_comment);
 13097            }
 98
 4458099            return sb.ToString();
 44580100        }
 101
 102        public override bool Equals([NotNullWhen(true)] object? obj) =>
 0103            obj is ViaHeaderValue other &&
 0104            // Note that for token and host case-insensitive comparison is used. Comments are compared using case-
 0105            // sensitive comparison.
 0106            string.Equals(_protocolVersion, other._protocolVersion, StringComparison.OrdinalIgnoreCase) &&
 0107            string.Equals(_receivedBy, other._receivedBy, StringComparison.OrdinalIgnoreCase) &&
 0108            string.Equals(_protocolName, other._protocolName, StringComparison.OrdinalIgnoreCase) &&
 0109            string.Equals(_comment, other._comment, StringComparison.Ordinal);
 110
 111        public override int GetHashCode() =>
 0112            HashCode.Combine(
 0113                StringComparer.OrdinalIgnoreCase.GetHashCode(_protocolVersion),
 0114                StringComparer.OrdinalIgnoreCase.GetHashCode(_receivedBy),
 0115                _protocolName is null ? 0 : StringComparer.OrdinalIgnoreCase.GetHashCode(_protocolName),
 0116                _comment);
 117
 118        public static ViaHeaderValue Parse(string input)
 0119        {
 0120            int index = 0;
 0121            return (ViaHeaderValue)GenericHeaderParser.SingleValueViaParser.ParseValue(input, null, ref index);
 0122        }
 123
 124        public static bool TryParse([NotNullWhen(true)] string? input, [NotNullWhen(true)] out ViaHeaderValue? parsedVal
 0125        {
 0126            int index = 0;
 0127            parsedValue = null;
 128
 0129            if (GenericHeaderParser.SingleValueViaParser.TryParseValue(input, null, ref index, out object? output))
 0130            {
 0131                parsedValue = (ViaHeaderValue)output!;
 0132                return true;
 133            }
 0134            return false;
 0135        }
 136
 137        internal static int GetViaLength(string? input, int startIndex, out object? parsedValue)
 29724138        {
 29724139            Debug.Assert(startIndex >= 0);
 140
 29724141            parsedValue = null;
 142
 29724143            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
 0144            {
 0145                return 0;
 146            }
 147
 148            // Read <protocolName> and <protocolVersion> in '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]
 29724149            int current = GetProtocolEndIndex(input, startIndex, out string? protocolName, out string? protocolVersion);
 150
 151            // If we reached the end of the string after reading protocolName/Version we return (we expect at least
 152            // <receivedBy> to follow). If reading protocolName/Version read 0 bytes, we return.
 29724153            if ((current == 0) || (current == input.Length))
 288154            {
 288155                return 0;
 156            }
 29436157            Debug.Assert(protocolVersion != null);
 158
 159            // Read <receivedBy> in '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]'
 29436160            int receivedByLength = HttpRuleParser.GetHostLength(input, current, true);
 29436161            if (receivedByLength == 0)
 384162            {
 384163                return 0;
 164            }
 165
 29052166            string receivedBy = input.Substring(current, receivedByLength);
 29052167            current += receivedByLength;
 168
 29052169            current += HttpRuleParser.GetWhitespaceLength(input, current);
 170
 29052171            string? comment = null;
 29052172            if ((current < input.Length) && (input[current] == '('))
 1950173            {
 174                // We have a <comment> in '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]'
 1950175                if (HttpRuleParser.GetCommentLength(input, current, out int commentLength) != HttpParseResult.Parsed)
 1804176                {
 1804177                    return 0; // We found a '(' character but it wasn't a valid comment. Abort.
 178                }
 179
 146180                comment = input.Substring(current, commentLength);
 181
 146182                current += commentLength;
 146183                current += HttpRuleParser.GetWhitespaceLength(input, current);
 146184            }
 185
 27248186            parsedValue = new ViaHeaderValue(protocolVersion, receivedBy, protocolName, comment, false);
 27248187            return current - startIndex;
 29724188        }
 189
 190        private static int GetProtocolEndIndex(string input, int startIndex, out string? protocolName,
 191            out string? protocolVersion)
 29724192        {
 193            // We have a string of the form '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]'. The first
 194            // token may either be the protocol name or protocol version. We'll only find out after reading the token
 195            // and by looking at the following character: If it is a '/' we just parsed the protocol name, otherwise
 196            // the protocol version.
 29724197            protocolName = null;
 29724198            protocolVersion = null;
 199
 29724200            int current = startIndex;
 29724201            int protocolVersionOrNameLength = HttpRuleParser.GetTokenLength(input, current);
 202
 29724203            if (protocolVersionOrNameLength == 0)
 68204            {
 68205                return 0;
 206            }
 207
 29656208            current = startIndex + protocolVersionOrNameLength;
 29656209            int whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, current);
 29656210            current += whitespaceLength;
 211
 29656212            if (current == input.Length)
 8213            {
 8214                return 0;
 215            }
 216
 29648217            if (input[current] == '/')
 192218            {
 219                // We parsed the protocol name
 192220                protocolName = input.Substring(startIndex, protocolVersionOrNameLength);
 221
 192222                current++; // skip the '/' delimiter
 192223                current += HttpRuleParser.GetWhitespaceLength(input, current);
 224
 192225                protocolVersionOrNameLength = HttpRuleParser.GetTokenLength(input, current);
 226
 192227                if (protocolVersionOrNameLength == 0)
 48228                {
 48229                    return 0; // We have a string "<token>/" followed by non-token chars. This is invalid.
 230                }
 231
 144232                protocolVersion = input.Substring(current, protocolVersionOrNameLength);
 233
 144234                current += protocolVersionOrNameLength;
 144235                whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, current);
 144236                current += whitespaceLength;
 144237            }
 238            else
 29456239            {
 29456240                protocolVersion = input.Substring(startIndex, protocolVersionOrNameLength);
 29456241            }
 242
 29600243            if (whitespaceLength == 0)
 164244            {
 164245                return 0; // We were able to parse [<protocolName>/]<protocolVersion> but it wasn't followed by a WS
 246            }
 247
 29436248            return current;
 29724249        }
 250
 251        object ICloneable.Clone()
 0252        {
 0253            return new ViaHeaderValue(this);
 0254        }
 255
 256        private static void CheckReceivedBy(string receivedBy)
 27248257        {
 27248258            ArgumentException.ThrowIfNullOrEmpty(receivedBy);
 259
 260            // 'receivedBy' can either be a host or a token. Since a token is a valid host, we only verify if the value
 261            // is a valid host.;
 27248262            if (HttpRuleParser.GetHostLength(receivedBy, 0, true) != receivedBy.Length)
 0263            {
 0264                throw new FormatException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_heade
 265            }
 27248266        }
 267    }
 268}