< Summary

Class:Azure.Storage.Blobs.Models.ContentRange
Assembly:Azure.Storage.Blobs
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs\src\Models\ContentRange.cs
Covered lines:0
Uncovered lines:36
Coverable lines:36
Total lines:149
Line coverage:0% (0 of 36)
Covered branches:0
Total branches:10
Branch coverage:0% (0 of 10)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor(...)-0%0%
get_Bytes()-0%100%
op_Equality(...)-0%100%
op_Inequality(...)-0%100%
op_Implicit(...)-0%100%
Equals(...)-0%0%
Equals(...)-0%100%
GetHashCode()-0%0%
ToString()-0%100%
get_Start()-0%100%
get_End()-0%100%
get_Size()-0%100%
get_Unit()-0%100%
.ctor(...)-0%100%
Parse(...)-0%0%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs\src\Models\ContentRange.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.ComponentModel;
 7using System.Globalization;
 8using System.Text;
 9
 10namespace Azure.Storage.Blobs.Models
 11{
 12    internal struct ContentRange
 13    {
 14        private const string WildcardMarker = "*";
 15
 16        public struct RangeUnit
 17        {
 18            internal const string BytesValue = "bytes";
 19
 20            private readonly string _value;
 21
 22            /// <summary>
 23            /// Initializes a new instance of the <see cref="RangeUnit"/> structure.
 24            /// </summary>
 25            /// <param name="value">The string value of the instance.</param>
 26            public RangeUnit(string value)
 27            {
 028                _value = value ?? throw new ArgumentNullException(nameof(value));
 029            }
 30
 31            /// <summary>
 32            /// Label for bytes as the measurement of content range.
 33            /// </summary>
 034            public static RangeUnit Bytes { get; } = new RangeUnit(BytesValue);
 35
 36            /// <summary>
 37            /// Determines if two <see cref="Unit"/> values are the same.
 38            /// </summary>
 39            /// <param name="left">The first <see cref="Unit"/> to compare.</param>
 40            /// <param name="right">The second <see cref="Unit"/> to compare.</param>
 41            /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are the same; otherwise, false.</r
 042            public static bool operator ==(RangeUnit left, RangeUnit right) => left.Equals(right);
 43
 44            /// <summary>
 45            /// Determines if two <see cref="RangeUnit"/> values are different.
 46            /// </summary>
 47            /// <param name="left">The first <see cref="RangeUnit"/> to compare.</param>
 48            /// <param name="right">The second <see cref="RangeUnit"/> to compare.</param>
 49            /// <returns>True if <paramref name="left"/> and <paramref name="right"/> are different; otherwise, false.</
 050            public static bool operator !=(RangeUnit left, RangeUnit right) => !left.Equals(right);
 51
 52            /// <summary>
 53            /// Converts a string to a <see cref="RangeUnit"/>.
 54            /// </summary>
 55            /// <param name="value">The string value to convert.</param>
 056            public static implicit operator RangeUnit(string value) => new RangeUnit(value);
 57
 58            /// <inheritdoc/>
 59            [EditorBrowsable(EditorBrowsableState.Never)]
 060            public override bool Equals(object obj) => obj is RangeUnit other && Equals(other);
 61
 62            /// <inheritdoc/>
 063            public bool Equals(RangeUnit other) => string.Equals(_value, other._value, StringComparison.Ordinal);
 64
 65            /// <inheritdoc/>
 66            [EditorBrowsable(EditorBrowsableState.Never)]
 067            public override int GetHashCode() => _value?.GetHashCode() ?? 0;
 68
 69            /// <inheritdoc/>
 070            public override string ToString() => _value;
 71        }
 72
 73        /// <summary>
 74        /// Inclusive index where the range starts, measured in this instance's <see cref="Unit"/>.
 75        /// </summary>
 076        public long? Start { get; }
 77
 78        /// <summary>
 79        /// Inclusive index where the range ends, measured in this instance's <see cref="Unit"/>.
 80        /// </summary>
 081        public long? End { get; }
 82
 83        /// <summary>
 84        /// Size of this range, measured in this instance's <see cref="Unit"/>.
 85        /// </summary>
 086        public long? Size { get; }
 87
 88        /// <summary>
 89        /// Unit this range is measured in. Generally "bytes".
 90        /// </summary>
 091        public RangeUnit Unit { get; }
 92
 93        public ContentRange(RangeUnit unit, long? start, long? end, long? size)
 94        {
 095            Start = start;
 096            End = end;
 097            Size = size;
 098            Unit = unit;
 099        }
 100
 101        public static ContentRange Parse(string headerValue)
 102        {
 103            /* Parse header value (e.g. "<unit> <start>-<end>/<blobSize>")
 104             * Either side of the "/" can be an asterisk, so possible results include:
 105             *   [<unit>, <start>, <end>, <blobSize>]
 106             *   [<unit>, "*", <blobSize>]
 107             *   [<unit>, <start>, <end>, "*"]
 108             *   [<unit>, "*", "*"] (unsure if possible but not hard to support)
 109             * "End" is the inclusive last byte; e.g. header "bytes 0-7/8" is the entire 8-byte blob
 110             */
 0111            var tokens = headerValue.Split(new char[] { ' ', '-', '/' }); // ["bytes", "<start>", "<end>", "<blobSize>"]
 112            string unit = default;
 0113            long? start = default;
 0114            long? end = default;
 0115            long? size = default;
 116
 117            try
 118            {
 119                // unit always first and always present
 0120                unit = tokens[0];
 121
 122                int blobSizeIndex;
 0123                if (tokens[1] == WildcardMarker) // [<unit>, "*", (<blobSize> | "*")]
 124                {
 0125                    blobSizeIndex = 2;
 126                }
 127                else // [<unit>, <start>, <end>, (<blobSize> | "*")]
 128                {
 0129                    blobSizeIndex = 3;
 130
 0131                    start = int.Parse(tokens[1], CultureInfo.InvariantCulture);
 0132                    end = int.Parse(tokens[2], CultureInfo.InvariantCulture);
 133                }
 134
 0135                var rawSize = tokens[blobSizeIndex];
 0136                if (rawSize != WildcardMarker)
 137                {
 0138                    size = int.Parse(rawSize, CultureInfo.InvariantCulture);
 139                }
 140
 0141                return new ContentRange(unit, start, end, size);
 142            }
 0143            catch (IndexOutOfRangeException)
 144            {
 0145                throw Errors.ParsingHttpRangeFailed();
 146            }
 0147        }
 148    }
 149}