< 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
 344225        private ViaHeaderValue(string protocolVersion, string receivedBy, string? protocolName, string? comment, bool _)
 344226        {
 27#if DEBUG
 28            // This constructor should only be used with already validated values.
 344229            new ViaHeaderValue(protocolVersion, receivedBy, protocolName, comment);
 30#endif
 31
 344232            _protocolVersion = protocolVersion;
 344233            _receivedBy = receivedBy;
 344234            _protocolName = protocolName;
 344235            _comment = comment;
 344236        }
 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
 344248        public ViaHeaderValue(string protocolVersion, string receivedBy, string? protocolName, string? comment)
 344249        {
 344250            HeaderUtilities.CheckValidToken(protocolVersion);
 344251            CheckReceivedBy(receivedBy);
 52
 344253            if (!string.IsNullOrEmpty(protocolName))
 127454            {
 127455                HeaderUtilities.CheckValidToken(protocolName);
 127456                _protocolName = protocolName;
 127457            }
 58
 344259            if (!string.IsNullOrEmpty(comment))
 060            {
 061                HeaderUtilities.CheckValidComment(comment);
 062                _comment = comment;
 063            }
 64
 344265            _protocolVersion = protocolVersion;
 344266            _receivedBy = receivedBy;
 344267        }
 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()
 465080        {
 465081            var sb = new ValueStringBuilder(stackalloc char[256]);
 82
 465083            if (!string.IsNullOrEmpty(_protocolName))
 167084            {
 167085                sb.Append(_protocolName);
 167086                sb.Append('/');
 167087            }
 88
 465089            sb.Append(_protocolVersion);
 465090            sb.Append(' ');
 465091            sb.Append(_receivedBy);
 92
 465093            if (!string.IsNullOrEmpty(_comment))
 094            {
 095                sb.Append(' ');
 096                sb.Append(_comment);
 097            }
 98
 465099            return sb.ToString();
 4650100        }
 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)
 3886138        {
 3886139            Debug.Assert(startIndex >= 0);
 140
 3886141            parsedValue = null;
 142
 3886143            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
 0144            {
 0145                return 0;
 146            }
 147
 148            // Read <protocolName> and <protocolVersion> in '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]
 3886149            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.
 3886153            if ((current == 0) || (current == input.Length))
 432154            {
 432155                return 0;
 156            }
 3454157            Debug.Assert(protocolVersion != null);
 158
 159            // Read <receivedBy> in '[<protocolName>/]<protocolVersion> <receivedBy> [<comment>]'
 3454160            int receivedByLength = HttpRuleParser.GetHostLength(input, current, true);
 3454161            if (receivedByLength == 0)
 12162            {
 12163                return 0;
 164            }
 165
 3442166            string receivedBy = input.Substring(current, receivedByLength);
 3442167            current += receivedByLength;
 168
 3442169            current += HttpRuleParser.GetWhitespaceLength(input, current);
 170
 3442171            string? comment = null;
 3442172            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
 3442186            parsedValue = new ViaHeaderValue(protocolVersion, receivedBy, protocolName, comment, false);
 3442187            return current - startIndex;
 3886188        }
 189
 190        private static int GetProtocolEndIndex(string input, int startIndex, out string? protocolName,
 191            out string? protocolVersion)
 3886192        {
 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.
 3886197            protocolName = null;
 3886198            protocolVersion = null;
 199
 3886200            int current = startIndex;
 3886201            int protocolVersionOrNameLength = HttpRuleParser.GetTokenLength(input, current);
 202
 3886203            if (protocolVersionOrNameLength == 0)
 100204            {
 100205                return 0;
 206            }
 207
 3786208            current = startIndex + protocolVersionOrNameLength;
 3786209            int whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, current);
 3786210            current += whitespaceLength;
 211
 3786212            if (current == input.Length)
 16213            {
 16214                return 0;
 215            }
 216
 3770217            if (input[current] == '/')
 1350218            {
 219                // We parsed the protocol name
 1350220                protocolName = input.Substring(startIndex, protocolVersionOrNameLength);
 221
 1350222                current++; // skip the '/' delimiter
 1350223                current += HttpRuleParser.GetWhitespaceLength(input, current);
 224
 1350225                protocolVersionOrNameLength = HttpRuleParser.GetTokenLength(input, current);
 226
 1350227                if (protocolVersionOrNameLength == 0)
 36228                {
 36229                    return 0; // We have a string "<token>/" followed by non-token chars. This is invalid.
 230                }
 231
 1314232                protocolVersion = input.Substring(current, protocolVersionOrNameLength);
 233
 1314234                current += protocolVersionOrNameLength;
 1314235                whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, current);
 1314236                current += whitespaceLength;
 1314237            }
 238            else
 2420239            {
 2420240                protocolVersion = input.Substring(startIndex, protocolVersionOrNameLength);
 2420241            }
 242
 3734243            if (whitespaceLength == 0)
 280244            {
 280245                return 0; // We were able to parse [<protocolName>/]<protocolVersion> but it wasn't followed by a WS
 246            }
 247
 3454248            return current;
 3886249        }
 250
 251        object ICloneable.Clone()
 0252        {
 0253            return new ViaHeaderValue(this);
 0254        }
 255
 256        private static void CheckReceivedBy(string receivedBy)
 3442257        {
 3442258            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.;
 3442262            if (HttpRuleParser.GetHostLength(receivedBy, 0, true) != receivedBy.Length)
 0263            {
 0264                throw new FormatException(SR.Format(System.Globalization.CultureInfo.InvariantCulture, SR.net_http_heade
 265            }
 3442266        }
 267    }
 268}