< Summary

Class:Azure.Core.Http.Multipart.HttpHeaderParser`1
Assembly:Azure.Storage.Blobs.Batch
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs.Batch\src\Shared\HttpHeaderParser.cs
Covered lines:0
Uncovered lines:47
Coverable lines:47
Total lines:177
Line coverage:0% (0 of 47)
Covered branches:0
Total branches:36
Branch coverage:0% (0 of 36)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-0%100%
get_SupportsMultipleValues()-0%100%
ParseValue(...)-0%0%
TryParseValues(...)-0%100%
TryParseStrictValues(...)-0%100%
TryParseValues(...)-0%0%
ParseValues(...)-0%100%
ParseStrictValues(...)-0%100%
ParseValues(...)-0%0%
ToString(...)-0%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs.Batch\src\Shared\HttpHeaderParser.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4// Copied from https://github.com/aspnet/AspNetCore/tree/master/src/Http/Headers/src
 5
 6using System;
 7using System.Collections.Generic;
 8using System.Diagnostics.Contracts;
 9using System.Globalization;
 10
 11#pragma warning disable IDE0018 // Inline declaration
 12#pragma warning disable IDE0032 // Use auto property
 13#pragma warning disable IDE0044 // Make field readonly
 14
 15namespace Azure.Core.Http.Multipart
 16{
 17    internal abstract class HttpHeaderParser<T>
 18    {
 19        private bool _supportsMultipleValues;
 20
 021        protected HttpHeaderParser(bool supportsMultipleValues)
 22        {
 023            _supportsMultipleValues = supportsMultipleValues;
 024        }
 25
 26        public bool SupportsMultipleValues
 27        {
 028            get { return _supportsMultipleValues; }
 29        }
 30
 31        // If a parser supports multiple values, a call to ParseValue/TryParseValue should return a value for 'index'
 32        // pointing to the next non-whitespace character after a delimiter. E.g. if called with a start index of 0
 33        // for string "value , second_value", then after the call completes, 'index' must point to 's', i.e. the first
 34        // non-whitespace after the separator ','.
 35        public abstract bool TryParseValue(StringSegment value, ref int index, out T parsedValue);
 36
 37        public T ParseValue(StringSegment value, ref int index)
 38        {
 39            // Index may be value.Length (e.g. both 0). This may be allowed for some headers (e.g. Accept but not
 40            // allowed by others (e.g. Content-Length). The parser has to decide if this is valid or not.
 41            Contract.Requires((value == null) || ((index >= 0) && (index <= value.Length)));
 42
 43            // If a parser returns 'null', it means there was no value, but that's valid (e.g. "Accept: "). The caller
 44            // can ignore the value.
 45            T result;
 046            if (!TryParseValue(value, ref index, out result))
 47            {
 048                throw new FormatException(string.Format(CultureInfo.InvariantCulture,
 049                    "The header contains invalid values at index {0}: '{1}'", index, value.Value ?? "<null>"));
 50            }
 051            return result;
 52        }
 53
 54        public virtual bool TryParseValues(IList<string> values, out IList<T> parsedValues)
 55        {
 056            return TryParseValues(values, strict: false, parsedValues: out parsedValues);
 57        }
 58
 59        public virtual bool TryParseStrictValues(IList<string> values, out IList<T> parsedValues)
 60        {
 061            return TryParseValues(values, strict: true, parsedValues: out parsedValues);
 62        }
 63
 64        protected virtual bool TryParseValues(IList<string> values, bool strict, out IList<T> parsedValues)
 65        {
 66            Contract.Assert(_supportsMultipleValues);
 67            // If a parser returns an empty list, it means there was no value, but that's valid (e.g. "Accept: "). The c
 68            // can ignore the value.
 069            parsedValues = null;
 070            List<T> results = null;
 071            if (values == null)
 72            {
 073                return false;
 74            }
 075            for (var i = 0; i < values.Count; i++)
 76            {
 077                var value = values[i];
 078                int index = 0;
 79
 080                while (!string.IsNullOrEmpty(value) && index < value.Length)
 81                {
 82                    T output;
 083                    if (TryParseValue(value, ref index, out output))
 84                    {
 85                        // The entry may not contain an actual value, like " , "
 086                        if (output != null)
 87                        {
 088                            if (results == null)
 89                            {
 090                                results = new List<T>();    // Allocate it only when used
 91                            }
 092                            results.Add(output);
 93                        }
 94                    }
 095                    else if (strict)
 96                    {
 097                        return false;
 98                    }
 99                    else
 100                    {
 101                        // Skip the invalid values and keep trying.
 0102                        index++;
 103                    }
 104                }
 105            }
 0106            if (results != null)
 107            {
 0108                parsedValues = results;
 0109                return true;
 110            }
 0111            return false;
 112        }
 113
 114        public virtual IList<T> ParseValues(IList<string> values)
 115        {
 0116            return ParseValues(values, strict: false);
 117        }
 118
 119        public virtual IList<T> ParseStrictValues(IList<string> values)
 120        {
 0121            return ParseValues(values, strict: true);
 122        }
 123
 124        protected virtual IList<T> ParseValues(IList<string> values, bool strict)
 125        {
 126            Contract.Assert(_supportsMultipleValues);
 127            // If a parser returns an empty list, it means there was no value, but that's valid (e.g. "Accept: "). The c
 128            // can ignore the value.
 0129            var parsedValues = new List<T>();
 0130            if (values == null)
 131            {
 0132                return parsedValues;
 133            }
 0134            foreach (var value in values)
 135            {
 0136                int index = 0;
 137
 0138                while (!string.IsNullOrEmpty(value) && index < value.Length)
 139                {
 140                    T output;
 0141                    if (TryParseValue(value, ref index, out output))
 142                    {
 143                        // The entry may not contain an actual value, like " , "
 0144                        if (output != null)
 145                        {
 0146                            parsedValues.Add(output);
 147                        }
 148                    }
 0149                    else if (strict)
 150                    {
 0151                        throw new FormatException(string.Format(CultureInfo.InvariantCulture,
 0152                            "The header contains invalid values at index {0}: '{1}'", index, value));
 153                    }
 154                    else
 155                    {
 156                        // Skip the invalid values and keep trying.
 0157                        index++;
 158                    }
 159                }
 160            }
 0161            return parsedValues;
 162        }
 163
 164        // If ValueType is a custom header value type (e.g. NameValueHeaderValue) it implements ToString() correctly.
 165        // However for existing types like int, byte[], DateTimeOffset we can't override ToString(). Therefore the
 166        // parser provides a ToString() virtual method that can be overridden by derived types to correctly serialize
 167        // values (e.g. byte[] to Base64 encoded string).
 168        // The default implementation is to just call ToString() on the value itself which is the right thing to do
 169        // for most headers (custom types, string, etc.).
 170        public virtual string ToString(object value)
 171        {
 172            Contract.Requires(value != null);
 173
 0174            return value.ToString();
 175        }
 176    }
 177}