< 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
62%
Covered lines: 52
Uncovered lines: 31
Coverable lines: 83
Total lines: 142
Line coverage: 62.6%
Branch coverage
61%
Covered branches: 21
Total branches: 34
Branch coverage: 61.7%
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(...)81.81%222294.28%
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    {
 611511        public string Tag { get; private init; }
 12
 611513        public bool IsWeak { get; private init; }
 14
 6715        public static EntityTagHeaderValue Any { get; } = new EntityTagHeaderValue("*", isWeak: false, false);
 16
 178717        private EntityTagHeaderValue(string tag, bool isWeak, bool _)
 178718        {
 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.
 178722            if (tag != "*")
 178623            {
 178624                new EntityTagHeaderValue(tag, isWeak);
 178625            }
 26#endif
 27
 178728            Tag = tag;
 178729            IsWeak = isWeak;
 178730        }
 31
 32        public EntityTagHeaderValue(string tag)
 033            : this(tag, false)
 034        {
 035        }
 36
 178637        public EntityTagHeaderValue(string tag, bool isWeak)
 178638        {
 178639            HeaderUtilities.CheckValidQuotedString(tag);
 40
 178641            Tag = tag;
 178642            IsWeak = isWeak;
 178643        }
 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() =>
 254254            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)
 323886        {
 323887            Debug.Assert(startIndex >= 0);
 88
 323889            parsedValue = null;
 90
 323891            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.
 323897            bool isWeak = false;
 323898            int current = startIndex;
 99
 3238100            char firstChar = input[startIndex];
 3238101            if (firstChar == '*')
 14102            {
 103                // We have '*' value, indicating "any" ETag.
 14104                parsedValue = Any;
 14105                current++;
 14106            }
 107            else
 3224108            {
 109                // The RFC defines 'W/' as prefix, but we'll be flexible and also accept lower-case 'w'.
 3224110                if ((firstChar == 'W') || (firstChar == 'w'))
 26111                {
 26112                    current++;
 113                    // We need at least 3 more chars: the '/' character followed by two quotes.
 26114                    if ((current + 2 >= input.Length) || (input[current] != '/'))
 14115                    {
 14116                        return 0;
 117                    }
 12118                    isWeak = true;
 12119                    current++; // we have a weak-entity tag.
 12120                    current += HttpRuleParser.GetWhitespaceLength(input, current);
 12121                }
 122
 3210123                if (current == input.Length || HttpRuleParser.GetQuotedStringLength(input, current, out int tagLength) !
 1424124                {
 1424125                    return 0;
 126                }
 127
 128                // Most of the time we'll have strong ETags without leading/trailing whitespace.
 1786129                Debug.Assert(tagLength != input.Length || (startIndex == 0 && !isWeak));
 130
 1786131                parsedValue = new EntityTagHeaderValue(input.Substring(current, tagLength), isWeak, false);
 132
 1786133                current += tagLength;
 1786134            }
 1800135            current += HttpRuleParser.GetWhitespaceLength(input, current);
 136
 1800137            return current - startIndex;
 3238138        }
 139
 0140        object ICloneable.Clone() => ReferenceEquals(this, Any) ? Any : new EntityTagHeaderValue(this);
 141    }
 142}