< 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
59%
Covered lines: 95
Uncovered lines: 66
Coverable lines: 161
Total lines: 268
Line coverage: 59%
Branch coverage
58%
Covered branches: 28
Total branches: 48
Branch coverage: 58.3%
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(...)75%4476.47%
.ctor(...)100%110%
ToString()75%4476.47%
Equals(...)0%880%
GetHashCode()0%220%
Parse(...)100%110%
TryParse(...)0%220%
GetViaLength(...)68.75%161667.74%
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
 263025        private ViaHeaderValue(string protocolVersion, string receivedBy, string? protocolName, string? comment, bool _)
 263026        {
 27#if DEBUG
 28            // This constructor should only be used with already validated values.
 263029            new ViaHeaderValue(protocolVersion, receivedBy, protocolName, comment);
 30#endif
 31
 263032            _protocolVersion = protocolVersion;
 263033            _receivedBy = receivedBy;
 263034            _protocolName = protocolName;
 263035            _comment = comment;
 263036        }
 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
 263048        public ViaHeaderValue(string protocolVersion, string receivedBy, string? protocolName, string? comment)
 263049        {
 263050            HeaderUtilities.CheckValidToken(protocolVersion);
 263051            CheckReceivedBy(receivedBy);
 52
 263053            if (!string.IsNullOrEmpty(protocolName))
 115254            {
 115255                HeaderUtilities.CheckValidToken(protocolName);
 115256                _protocolName = protocolName;
 115257            }
 58
 263059            if (!string.IsNullOrEmpty(comment))
 060            {
 061                HeaderUtilities.CheckValidComment(comment);
 062                _comment = comment;
 063            }
 64
 263065            _protocolVersion = protocolVersion;
 263066            _receivedBy = receivedBy;
 263067        }
 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()
 335080        {
 335081            var sb = new ValueStringBuilder(stackalloc char[256]);
 82
 335083            if (!string.IsNullOrEmpty(_protocolName))
 150084            {
 150085                sb.Append(_protocolName);
 150086                sb.Append('/');
 150087            }
 88
 335089            sb.Append(_protocolVersion);
 335090            sb.Append(' ');
 335091            sb.Append(_receivedBy);
 92
 335093            if (!string.IsNullOrEmpty(_comment))
 094            {
 095                sb.Append(' ');
 096                sb.Append(_comment);
 097            }
 98
 335099            return sb.ToString();
 3350100        }
 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)
 3058138        {
 3058139            Debug.Assert(startIndex >= 0);
 140
 3058141            parsedValue = null;
 142
 3058143            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
 0144            {
 0145                return 0;
 146            }
 147
 148            // Read <protocolName> and <protocolVersion> in '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]
 3058149            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.
 3058153            if ((current == 0) || (current == input.Length))
 416154            {
 416155                return 0;
 156            }
 2642157            Debug.Assert(protocolVersion != null);
 158
 159            // Read <receivedBy> in '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]'
 2642160            int receivedByLength = HttpRuleParser.GetHostLength(input, current, true);
 2642161            if (receivedByLength == 0)
 12162            {
 12163                return 0;
 164            }
 165
 2630166            string receivedBy = input.Substring(current, receivedByLength);
 2630167            current += receivedByLength;
 168
 2630169            current += HttpRuleParser.GetWhitespaceLength(input, current);
 170
 2630171            string? comment = null;
 2630172            if ((current < input.Length) && (input[current] == '('))
 0173            {
 174                // We have a <comment> in '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]'
 0175                if (HttpRuleParser.GetCommentLength(input, current, out int commentLength) != HttpParseResult.Parsed)
 0176                {
 0177                    return 0; // We found a '(' character but it wasn't a valid comment. Abort.
 178                }
 179
 0180                comment = input.Substring(current, commentLength);
 181
 0182                current += commentLength;
 0183                current += HttpRuleParser.GetWhitespaceLength(input, current);
 0184            }
 185
 2630186            parsedValue = new ViaHeaderValue(protocolVersion, receivedBy, protocolName, comment, false);
 2630187            return current - startIndex;
 3058188        }
 189
 190        private static int GetProtocolEndIndex(string input, int startIndex, out string? protocolName,
 191            out string? protocolVersion)
 3058192        {
 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.
 3058197            protocolName = null;
 3058198            protocolVersion = null;
 199
 3058200            int current = startIndex;
 3058201            int protocolVersionOrNameLength = HttpRuleParser.GetTokenLength(input, current);
 202
 3058203            if (protocolVersionOrNameLength == 0)
 92204            {
 92205                return 0;
 206            }
 207
 2966208            current = startIndex + protocolVersionOrNameLength;
 2966209            int whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, current);
 2966210            current += whitespaceLength;
 211
 2966212            if (current == input.Length)
 16213            {
 16214                return 0;
 215            }
 216
 2950217            if (input[current] == '/')
 1228218            {
 219                // We parsed the protocol name
 1228220                protocolName = input.Substring(startIndex, protocolVersionOrNameLength);
 221
 1228222                current++; // skip the '/' delimiter
 1228223                current += HttpRuleParser.GetWhitespaceLength(input, current);
 224
 1228225                protocolVersionOrNameLength = HttpRuleParser.GetTokenLength(input, current);
 226
 1228227                if (protocolVersionOrNameLength == 0)
 36228                {
 36229                    return 0; // We have a string "<token>/" followed by non-token chars. This is invalid.
 230                }
 231
 1192232                protocolVersion = input.Substring(current, protocolVersionOrNameLength);
 233
 1192234                current += protocolVersionOrNameLength;
 1192235                whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, current);
 1192236                current += whitespaceLength;
 1192237            }
 238            else
 1722239            {
 1722240                protocolVersion = input.Substring(startIndex, protocolVersionOrNameLength);
 1722241            }
 242
 2914243            if (whitespaceLength == 0)
 272244            {
 272245                return 0; // We were able to parse [<protocolName>/]<protocolVersion> but it wasn't followed by a WS
 246            }
 247
 2642248            return current;
 3058249        }
 250
 251        object ICloneable.Clone()
 0252        {
 0253            return new ViaHeaderValue(this);
 0254        }
 255
 256        private static void CheckReceivedBy(string receivedBy)
 2630257        {
 2630258            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.;
 2630262            if (HttpRuleParser.GetHostLength(receivedBy, 0, true) != receivedBy.Length)
 0263            {
 0264                throw new FormatException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_heade
 265            }
 2630266        }
 267    }
 268}