< Summary

Information
Class: System.Net.Http.Headers.EntityTagHeaderValue
Assembly: System.Net.Http
File(s): D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\Headers\EntityTagHeaderValue.cs
Line coverage
57%
Covered lines: 48
Uncovered lines: 35
Coverable lines: 83
Total lines: 142
Line coverage: 57.8%
Branch coverage
58%
Covered branches: 20
Total branches: 34
Branch coverage: 58.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%22100%
.ctor(...)100%110%
.ctor(...)100%11100%
.ctor(...)100%110%
ToString()50%22100%
Equals(...)0%440%
GetHashCode()100%110%
Parse(...)100%110%
TryParse(...)0%220%
GetEntityTagLength(...)77.27%222282.85%
System.ICloneable.Clone()0%220%

File(s)

D:\runner\runtime\src\libraries\System.Net.Http\src\System\Net\Http\Headers\EntityTagHeaderValue.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;
 6
 7namespace System.Net.Http.Headers
 8{
 9    public class EntityTagHeaderValue : ICloneable
 10    {
 224211        public string Tag { get; private init; }
 12
 224213        public bool IsWeak { get; private init; }
 14
 29215        public static EntityTagHeaderValue Any { get; } = new EntityTagHeaderValue("*", isWeak: false, false);
 16
 81417        private EntityTagHeaderValue(string tag, bool isWeak, bool _)
 81418        {
 19#if DEBUG
 20            // This constructor should only be used with already validated values.
 21            // "*" is a special case that can only be created via the static Any property.
 81422            if (tag != "*")
 81323            {
 81324                new EntityTagHeaderValue(tag, isWeak);
 81325            }
 26#endif
 27
 81428            Tag = tag;
 81429            IsWeak = isWeak;
 81430        }
 31
 32        public EntityTagHeaderValue(string tag)
 033            : this(tag, false)
 034        {
 035        }
 36
 81337        public EntityTagHeaderValue(string tag, bool isWeak)
 81338        {
 81339            HeaderUtilities.CheckValidQuotedString(tag);
 40
 81341            Tag = tag;
 81342            IsWeak = isWeak;
 81343        }
 44
 045        private EntityTagHeaderValue(EntityTagHeaderValue source)
 046        {
 047            Debug.Assert(source != null);
 48
 049            Tag = source.Tag;
 050            IsWeak = source.IsWeak;
 051        }
 52
 53        public override string ToString() =>
 61554            IsWeak ? $"W/{Tag}" : Tag;
 55
 56        public override bool Equals([NotNullWhen(true)] object? obj) =>
 057            obj is EntityTagHeaderValue other &&
 058            IsWeak == other.IsWeak &&
 059            // Since the tag is a quoted-string we treat it case-sensitive.
 060            string.Equals(Tag, other.Tag, StringComparison.Ordinal);
 61
 62        public override int GetHashCode() =>
 063            HashCode.Combine(Tag, IsWeak);
 64
 65        public static EntityTagHeaderValue Parse(string input)
 066        {
 067            int index = 0;
 068            return (EntityTagHeaderValue)GenericHeaderParser.SingleValueEntityTagParser.ParseValue(
 069                input, null, ref index);
 070        }
 71
 72        public static bool TryParse([NotNullWhen(true)] string? input, [NotNullWhen(true)] out EntityTagHeaderValue? par
 073        {
 074            int index = 0;
 075            parsedValue = null;
 76
 077            if (GenericHeaderParser.SingleValueEntityTagParser.TryParseValue(input, null, ref index, out object? output)
 078            {
 079                parsedValue = (EntityTagHeaderValue)output!;
 080                return true;
 81            }
 082            return false;
 083        }
 84
 85        internal static int GetEntityTagLength(string? input, int startIndex, out EntityTagHeaderValue? parsedValue)
 144086        {
 144087            Debug.Assert(startIndex >= 0);
 88
 144089            parsedValue = null;
 90
 144091            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
 092            {
 093                return 0;
 94            }
 95
 96            // Caller must remove leading whitespace. If not, we'll return 0.
 144097            bool isWeak = false;
 144098            int current = startIndex;
 99
 1440100            char firstChar = input[startIndex];
 1440101            if (firstChar == '*')
 277102            {
 103                // We have '*' value, indicating "any" ETag.
 277104                parsedValue = Any;
 277105                current++;
 277106            }
 107            else
 1163108            {
 109                // The RFC defines 'W/' as prefix, but we'll be flexible and also accept lower-case 'w'.
 1163110                if ((firstChar == 'W') || (firstChar == 'w'))
 30111                {
 30112                    current++;
 113                    // We need at least 3 more chars: the '/' character followed by two quotes.
 30114                    if ((current + 2 >= input.Length) || (input[current] != '/'))
 30115                    {
 30116                        return 0;
 117                    }
 0118                    isWeak = true;
 0119                    current++; // we have a weak-entity tag.
 0120                    current += HttpRuleParser.GetWhitespaceLength(input, current);
 0121                }
 122
 1133123                if (current == input.Length || HttpRuleParser.GetQuotedStringLength(input, current, out int tagLength) !
 320124                {
 320125                    return 0;
 126                }
 127
 128                // Most of the time we'll have strong ETags without leading/trailing whitespace.
 813129                Debug.Assert(tagLength != input.Length || (startIndex == 0 && !isWeak));
 130
 813131                parsedValue = new EntityTagHeaderValue(input.Substring(current, tagLength), isWeak, false);
 132
 813133                current += tagLength;
 813134            }
 1090135            current += HttpRuleParser.GetWhitespaceLength(input, current);
 136
 1090137            return current - startIndex;
 1440138        }
 139
 0140        object ICloneable.Clone() => ReferenceEquals(this, Any) ? Any : new EntityTagHeaderValue(this);
 141    }
 142}