< Summary

Class:Azure.Core.Http.Multipart.StringValues
Assembly:Azure.Storage.Blobs.Batch
File(s):C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs.Batch\src\Shared\StringValues.cs
Covered lines:8
Uncovered lines:197
Coverable lines:205
Total lines:681
Line coverage:3.9% (8 of 205)
Covered branches:3
Total branches:114
Branch coverage:2.6% (3 of 114)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.cctor()-0%100%
.ctor(...)-100%100%
.ctor(...)-0%100%
op_Implicit(...)-0%100%
op_Implicit(...)-0%100%
op_Implicit(...)-0%100%
op_Implicit(...)-0%100%
get_Count()-50%25%
System.Collections.Generic.ICollection<System.String>.get_IsReadOnly()-0%100%
System.Collections.Generic.IList<System.String>.get_Item(...)-0%100%
System.Collections.Generic.IList<System.String>.set_Item(...)-0%100%
get_Item(...)-50%33.33%
OutOfBounds()-0%100%
ToString()-0%0%
GetStringValue()-0%0%
ToArray()-0%0%
GetArrayValue()-0%0%
System.Collections.Generic.IList<System.String>.IndexOf(...)-0%100%
IndexOf(...)-0%0%
System.Collections.Generic.ICollection<System.String>.Contains(...)-0%100%
System.Collections.Generic.ICollection<System.String>.CopyTo(...)-0%100%
CopyTo(...)-0%0%
System.Collections.Generic.ICollection<System.String>.Add(...)-0%100%
System.Collections.Generic.IList<System.String>.Insert(...)-0%100%
System.Collections.Generic.ICollection<System.String>.Remove(...)-0%100%
System.Collections.Generic.IList<System.String>.RemoveAt(...)-0%100%
System.Collections.Generic.ICollection<System.String>.Clear()-0%100%
GetEnumerator()-0%100%
System.Collections.Generic.IEnumerable<System.String>.GetEnumerator()-0%100%
System.Collections.IEnumerable.GetEnumerator()-0%100%
IsNullOrEmpty(...)-0%0%
Concat(...)-0%0%
Concat(...)-0%0%
Concat(...)-0%0%
Equals(...)-0%0%
op_Equality(...)-0%100%
op_Inequality(...)-0%100%
Equals(...)-0%100%
Equals(...)-0%100%
Equals(...)-0%100%
Equals(...)-0%100%
Equals(...)-0%100%
Equals(...)-0%100%
Equals(...)-0%100%
op_Equality(...)-0%100%
op_Inequality(...)-0%100%
op_Equality(...)-0%100%
op_Inequality(...)-0%100%
op_Equality(...)-0%100%
op_Inequality(...)-0%100%
op_Equality(...)-0%100%
op_Inequality(...)-0%100%
op_Equality(...)-0%100%
op_Inequality(...)-0%100%
op_Equality(...)-0%100%
op_Inequality(...)-0%100%
Equals(...)-0%0%
GetHashCode()-0%0%
.ctor(...)-0%0%
.ctor(...)-0%100%
MoveNext()-0%0%
get_Current()-0%100%
System.Collections.IEnumerator.get_Current()-0%100%
System.Collections.IEnumerator.Reset()-0%100%
Dispose()-0%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\storage\Azure.Storage.Blobs.Batch\src\Shared\StringValues.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/Extensions/tree/master/src/Primitives/src
 5
 6using System;
 7using System.Collections;
 8using System.Collections.Generic;
 9using System.Diagnostics;
 10using System.Runtime.CompilerServices;
 11
 12#pragma warning disable IDE0032 // Use auto property
 13#pragma warning disable IDE0066 // Use switch expression
 14
 15namespace Azure.Core.Http.Multipart
 16{
 17    /// <summary>
 18    /// Represents zero/null, one, or many strings in an efficient way.
 19    /// </summary>
 20    internal readonly struct StringValues : IList<string>, IReadOnlyList<string>, IEquatable<StringValues>, IEquatable<s
 21    {
 022        public static readonly StringValues Empty = new StringValues(Array.Empty<string>());
 23
 24        private readonly object _values;
 25
 26        public StringValues(string value)
 27        {
 254028            _values = value;
 254029        }
 30
 31        public StringValues(string[] values)
 32        {
 033            _values = values;
 034        }
 35
 36        public static implicit operator StringValues(string value)
 37        {
 038            return new StringValues(value);
 39        }
 40
 41        public static implicit operator StringValues(string[] values)
 42        {
 043            return new StringValues(values);
 44        }
 45
 46        public static implicit operator string(StringValues values)
 47        {
 048            return values.GetStringValue();
 49        }
 50
 51        public static implicit operator string[](StringValues value)
 52        {
 053            return value.GetArrayValue();
 54        }
 55
 56        public int Count
 57        {
 58            [MethodImpl(MethodImplOptions.AggressiveInlining)]
 59            get
 60            {
 61                // Take local copy of _values so type checks remain valid even if the StringValues is overwritten in mem
 126862                var value = _values;
 126863                if (value is string)
 64                {
 126865                    return 1;
 66                }
 067                if (value is null)
 68                {
 069                    return 0;
 70                }
 71                else
 72                {
 73                    // Not string, not null, can only be string[]
 074                    return Unsafe.As<string[]>(value).Length;
 75                }
 76            }
 77        }
 78
 79        bool ICollection<string>.IsReadOnly
 80        {
 081            get { return true; }
 82        }
 83
 84        string IList<string>.this[int index]
 85        {
 086            get { return this[index]; }
 087            set { throw new NotSupportedException(); }
 88        }
 89
 90        public string this[int index]
 91        {
 92            [MethodImpl(MethodImplOptions.AggressiveInlining)]
 93            get
 94            {
 95                // Take local copy of _values so type checks remain valid even if the StringValues is overwritten in mem
 126896                var value = _values;
 126897                if (index == 0 && value is string str)
 98                {
 126899                    return str;
 100                }
 0101                else if (value != null)
 102                {
 103                    // Not string, not null, can only be string[]
 0104                    return Unsafe.As<string[]>(value)[index]; // may throw
 105                }
 106                else
 107                {
 0108                    return OutOfBounds(); // throws
 109                }
 110            }
 111        }
 112
 113        [MethodImpl(MethodImplOptions.NoInlining)]
 114        private static string OutOfBounds()
 115        {
 0116            return Array.Empty<string>()[0]; // throws
 117        }
 118
 119        public override string ToString()
 120        {
 0121            return GetStringValue() ?? string.Empty;
 122        }
 123
 124        private string GetStringValue()
 125        {
 126            // Take local copy of _values so type checks remain valid even if the StringValues is overwritten in memory
 0127            var value = _values;
 0128            if (value is string s)
 129            {
 0130                return s;
 131            }
 132            else
 133            {
 0134                return GetStringValueFromArray(value);
 135            }
 136
 137            static string GetStringValueFromArray(object value)
 138            {
 0139                if (value is null)
 140                {
 0141                    return null;
 142                }
 143
 144                Debug.Assert(value is string[]);
 145                // value is not null or string, array, can only be string[]
 0146                var values = Unsafe.As<string[]>(value);
 0147                switch (values.Length)
 148                {
 149                    case 0:
 0150                        return null;
 151                    case 1:
 0152                        return values[0];
 153                    default:
 0154                        return GetJoinedStringValueFromArray(values);
 155                }
 156            }
 157
 158            static string GetJoinedStringValueFromArray(string[] values)
 159            {
 160                // Calculate final length
 0161                var length = 0;
 0162                for (var i = 0; i < values.Length; i++)
 163                {
 0164                    var value = values[i];
 165                    // Skip null and empty values
 0166                    if (value != null && value.Length > 0)
 167                    {
 0168                        if (length > 0)
 169                        {
 170                            // Add seperator
 0171                            length++;
 172                        }
 173
 0174                        length += value.Length;
 175                    }
 176                }
 177#if NETCOREAPP
 178                // Create the new string
 179                return string.Create(length, values, (span, strings) => {
 180                    var offset = 0;
 181                    // Skip null and empty values
 182                    for (var i = 0; i < strings.Length; i++)
 183                    {
 184                        var value = strings[i];
 185                        if (value != null && value.Length > 0)
 186                        {
 187                            if (offset > 0)
 188                            {
 189                                // Add seperator
 190                                span[offset] = ',';
 191                                offset++;
 192                            }
 193
 194                            value.AsSpan().CopyTo(span.Slice(offset));
 195                            offset += value.Length;
 196                        }
 197                    }
 198                });
 199#else
 200#pragma warning disable CS0618
 0201                var sb = new InplaceStringBuilder(length);
 202#pragma warning restore CS0618
 0203                var hasAdded = false;
 204                // Skip null and empty values
 0205                for (var i = 0; i < values.Length; i++)
 206                {
 0207                    var value = values[i];
 0208                    if (value != null && value.Length > 0)
 209                    {
 0210                        if (hasAdded)
 211                        {
 212                            // Add seperator
 0213                            sb.Append(',');
 214                        }
 215
 0216                        sb.Append(value);
 0217                        hasAdded = true;
 218                    }
 219                }
 220
 0221                return sb.ToString();
 222#endif
 223            }
 224        }
 225
 226        public string[] ToArray()
 227        {
 0228            return GetArrayValue() ?? Array.Empty<string>();
 229        }
 230
 231        private string[] GetArrayValue()
 232        {
 233            // Take local copy of _values so type checks remain valid even if the StringValues is overwritten in memory
 0234            var value = _values;
 0235            if (value is string[] values)
 236            {
 0237                return values;
 238            }
 0239            else if (value != null)
 240            {
 241                // value not array, can only be string
 0242                return new[] { Unsafe.As<string>(value) };
 243            }
 244            else
 245            {
 0246                return null;
 247            }
 248        }
 249
 250        int IList<string>.IndexOf(string item)
 251        {
 0252            return IndexOf(item);
 253        }
 254
 255        private int IndexOf(string item)
 256        {
 257            // Take local copy of _values so type checks remain valid even if the StringValues is overwritten in memory
 0258            var value = _values;
 0259            if (value is string[] values)
 260            {
 0261                for (int i = 0; i < values.Length; i++)
 262                {
 0263                    if (string.Equals(values[i], item, StringComparison.Ordinal))
 264                    {
 0265                        return i;
 266                    }
 267                }
 0268                return -1;
 269            }
 270
 0271            if (value != null)
 272            {
 273                // value not array, can only be string
 0274                return string.Equals(Unsafe.As<string>(value), item, StringComparison.Ordinal) ? 0 : -1;
 275            }
 276
 0277            return -1;
 278        }
 279
 280        bool ICollection<string>.Contains(string item)
 281        {
 0282            return IndexOf(item) >= 0;
 283        }
 284
 285        void ICollection<string>.CopyTo(string[] array, int arrayIndex)
 286        {
 0287            CopyTo(array, arrayIndex);
 0288        }
 289
 290        private void CopyTo(string[] array, int arrayIndex)
 291        {
 292            // Take local copy of _values so type checks remain valid even if the StringValues is overwritten in memory
 0293            var value = _values;
 0294            if (value is string[] values)
 295            {
 0296                Array.Copy(values, 0, array, arrayIndex, values.Length);
 0297                return;
 298            }
 299
 0300            if (value != null)
 301            {
 0302                if (array == null)
 303                {
 0304                    throw new ArgumentNullException(nameof(array));
 305                }
 0306                if (arrayIndex < 0)
 307                {
 0308                    throw new ArgumentOutOfRangeException(nameof(arrayIndex));
 309                }
 0310                if (array.Length - arrayIndex < 1)
 311                {
 0312                    throw new ArgumentException(
 0313                        $"'{nameof(array)}' is not long enough to copy all the items in the collection. Check '{nameof(a
 314                }
 315
 316                // value not array, can only be string
 0317                array[arrayIndex] = Unsafe.As<string>(value);
 318            }
 0319        }
 320
 321        void ICollection<string>.Add(string item)
 322        {
 0323            throw new NotSupportedException();
 324        }
 325
 326        void IList<string>.Insert(int index, string item)
 327        {
 0328            throw new NotSupportedException();
 329        }
 330
 331        bool ICollection<string>.Remove(string item)
 332        {
 0333            throw new NotSupportedException();
 334        }
 335
 336        void IList<string>.RemoveAt(int index)
 337        {
 0338            throw new NotSupportedException();
 339        }
 340
 341        void ICollection<string>.Clear()
 342        {
 0343            throw new NotSupportedException();
 344        }
 345
 346        public Enumerator GetEnumerator()
 347        {
 0348            return new Enumerator(_values);
 349        }
 350
 351        IEnumerator<string> IEnumerable<string>.GetEnumerator()
 352        {
 0353            return GetEnumerator();
 354        }
 355
 356        IEnumerator IEnumerable.GetEnumerator()
 357        {
 0358            return GetEnumerator();
 359        }
 360
 361        public static bool IsNullOrEmpty(StringValues value)
 362        {
 0363            var data = value._values;
 0364            if (data is null)
 365            {
 0366                return true;
 367            }
 0368            if (data is string[] values)
 369            {
 0370                switch (values.Length)
 371                {
 372                    case 0:
 0373                        return true;
 374                    case 1:
 0375                        return string.IsNullOrEmpty(values[0]);
 376                    default:
 0377                        return false;
 378                }
 379            }
 380            else
 381            {
 382                // Not array, can only be string
 0383                return string.IsNullOrEmpty(Unsafe.As<string>(data));
 384            }
 385        }
 386
 387        public static StringValues Concat(StringValues values1, StringValues values2)
 388        {
 0389            var count1 = values1.Count;
 0390            var count2 = values2.Count;
 391
 0392            if (count1 == 0)
 393            {
 0394                return values2;
 395            }
 396
 0397            if (count2 == 0)
 398            {
 0399                return values1;
 400            }
 401
 0402            var combined = new string[count1 + count2];
 0403            values1.CopyTo(combined, 0);
 0404            values2.CopyTo(combined, count1);
 0405            return new StringValues(combined);
 406        }
 407
 408        public static StringValues Concat(in StringValues values, string value)
 409        {
 0410            if (value == null)
 411            {
 0412                return values;
 413            }
 414
 0415            var count = values.Count;
 0416            if (count == 0)
 417            {
 0418                return new StringValues(value);
 419            }
 420
 0421            var combined = new string[count + 1];
 0422            values.CopyTo(combined, 0);
 0423            combined[count] = value;
 0424            return new StringValues(combined);
 425        }
 426
 427        public static StringValues Concat(string value, in StringValues values)
 428        {
 0429            if (value == null)
 430            {
 0431                return values;
 432            }
 433
 0434            var count = values.Count;
 0435            if (count == 0)
 436            {
 0437                return new StringValues(value);
 438            }
 439
 0440            var combined = new string[count + 1];
 0441            combined[0] = value;
 0442            values.CopyTo(combined, 1);
 0443            return new StringValues(combined);
 444        }
 445
 446        public static bool Equals(StringValues left, StringValues right)
 447        {
 0448            var count = left.Count;
 449
 0450            if (count != right.Count)
 451            {
 0452                return false;
 453            }
 454
 0455            for (var i = 0; i < count; i++)
 456            {
 0457                if (left[i] != right[i])
 458                {
 0459                    return false;
 460                }
 461            }
 462
 0463            return true;
 464        }
 465
 466        public static bool operator ==(StringValues left, StringValues right)
 467        {
 0468            return Equals(left, right);
 469        }
 470
 471        public static bool operator !=(StringValues left, StringValues right)
 472        {
 0473            return !Equals(left, right);
 474        }
 475
 476        public bool Equals(StringValues other)
 477        {
 0478            return Equals(this, other);
 479        }
 480
 481        public static bool Equals(string left, StringValues right)
 482        {
 0483            return Equals(new StringValues(left), right);
 484        }
 485
 486        public static bool Equals(StringValues left, string right)
 487        {
 0488            return Equals(left, new StringValues(right));
 489        }
 490
 491        public bool Equals(string other)
 492        {
 0493            return Equals(this, new StringValues(other));
 494        }
 495
 496        public static bool Equals(string[] left, StringValues right)
 497        {
 0498            return Equals(new StringValues(left), right);
 499        }
 500
 501        public static bool Equals(StringValues left, string[] right)
 502        {
 0503            return Equals(left, new StringValues(right));
 504        }
 505
 506        public bool Equals(string[] other)
 507        {
 0508            return Equals(this, new StringValues(other));
 509        }
 510
 511        public static bool operator ==(StringValues left, string right)
 512        {
 0513            return Equals(left, new StringValues(right));
 514        }
 515
 516        public static bool operator !=(StringValues left, string right)
 517        {
 0518            return !Equals(left, new StringValues(right));
 519        }
 520
 521        public static bool operator ==(string left, StringValues right)
 522        {
 0523            return Equals(new StringValues(left), right);
 524        }
 525
 526        public static bool operator !=(string left, StringValues right)
 527        {
 0528            return !Equals(new StringValues(left), right);
 529        }
 530
 531        public static bool operator ==(StringValues left, string[] right)
 532        {
 0533            return Equals(left, new StringValues(right));
 534        }
 535
 536        public static bool operator !=(StringValues left, string[] right)
 537        {
 0538            return !Equals(left, new StringValues(right));
 539        }
 540
 541        public static bool operator ==(string[] left, StringValues right)
 542        {
 0543            return Equals(new StringValues(left), right);
 544        }
 545
 546        public static bool operator !=(string[] left, StringValues right)
 547        {
 0548            return !Equals(new StringValues(left), right);
 549        }
 550
 551        public static bool operator ==(StringValues left, object right)
 552        {
 0553            return left.Equals(right);
 554        }
 555
 556        public static bool operator !=(StringValues left, object right)
 557        {
 0558            return !left.Equals(right);
 559        }
 560        public static bool operator ==(object left, StringValues right)
 561        {
 0562            return right.Equals(left);
 563        }
 564
 565        public static bool operator !=(object left, StringValues right)
 566        {
 0567            return !right.Equals(left);
 568        }
 569
 570        public override bool Equals(object obj)
 571        {
 0572            if (obj == null)
 573            {
 0574                return Equals(this, StringValues.Empty);
 575            }
 576
 0577            if (obj is string)
 578            {
 0579                return Equals(this, (string)obj);
 580            }
 581
 0582            if (obj is string[])
 583            {
 0584                return Equals(this, (string[])obj);
 585            }
 586
 0587            if (obj is StringValues)
 588            {
 0589                return Equals(this, (StringValues)obj);
 590            }
 591
 0592            return false;
 593        }
 594
 595        public override int GetHashCode()
 596        {
 0597            var value = _values;
 0598            if (value is string[] values)
 599            {
 0600                if (Count == 1)
 601                {
 0602                    return Unsafe.As<string>(this[0])?.GetHashCode() ?? Count.GetHashCode();
 603                }
 0604                var hcc = new HashCodeCombiner();
 0605                for (var i = 0; i < values.Length; i++)
 606                {
 0607                    hcc.Add(values[i]);
 608                }
 0609                return hcc.CombinedHash;
 610            }
 611            else
 612            {
 0613                return Unsafe.As<string>(value)?.GetHashCode() ?? Count.GetHashCode();
 614            }
 615        }
 616
 617        public struct Enumerator : IEnumerator<string>
 618        {
 619            private readonly string[] _values;
 620            private string _current;
 621            private int _index;
 622
 623            internal Enumerator(object value)
 624            {
 0625                if (value is string str)
 626                {
 0627                    _values = null;
 0628                    _current = str;
 629                }
 630                else
 631                {
 0632                    _current = null;
 0633                    _values = Unsafe.As<string[]>(value);
 634                }
 0635                _index = 0;
 0636            }
 637
 0638            public Enumerator(ref StringValues values) : this(values._values)
 0639            { }
 640
 641            public bool MoveNext()
 642            {
 0643                var index = _index;
 0644                if (index < 0)
 645                {
 0646                    return false;
 647                }
 648
 0649                var values = _values;
 0650                if (values != null)
 651                {
 0652                    if ((uint)index < (uint)values.Length)
 653                    {
 0654                        _index = index + 1;
 0655                        _current = values[index];
 0656                        return true;
 657                    }
 658
 0659                    _index = -1;
 0660                    return false;
 661                }
 662
 0663                _index = -1; // sentinel value
 0664                return _current != null;
 665            }
 666
 0667            public string Current => _current;
 668
 0669            object IEnumerator.Current => _current;
 670
 671            void IEnumerator.Reset()
 672            {
 0673                throw new NotSupportedException();
 674            }
 675
 676            public void Dispose()
 677            {
 0678            }
 679        }
 680    }
 681}

Methods/Properties

.cctor()
.ctor(...)
.ctor(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
op_Implicit(...)
get_Count()
System.Collections.Generic.ICollection<System.String>.get_IsReadOnly()
System.Collections.Generic.IList<System.String>.get_Item(...)
System.Collections.Generic.IList<System.String>.set_Item(...)
get_Item(...)
OutOfBounds()
ToString()
GetStringValue()
ToArray()
GetArrayValue()
System.Collections.Generic.IList<System.String>.IndexOf(...)
IndexOf(...)
System.Collections.Generic.ICollection<System.String>.Contains(...)
System.Collections.Generic.ICollection<System.String>.CopyTo(...)
CopyTo(...)
System.Collections.Generic.ICollection<System.String>.Add(...)
System.Collections.Generic.IList<System.String>.Insert(...)
System.Collections.Generic.ICollection<System.String>.Remove(...)
System.Collections.Generic.IList<System.String>.RemoveAt(...)
System.Collections.Generic.ICollection<System.String>.Clear()
GetEnumerator()
System.Collections.Generic.IEnumerable<System.String>.GetEnumerator()
System.Collections.IEnumerable.GetEnumerator()
IsNullOrEmpty(...)
Concat(...)
Concat(...)
Concat(...)
Equals(...)
op_Equality(...)
op_Inequality(...)
Equals(...)
Equals(...)
Equals(...)
Equals(...)
Equals(...)
Equals(...)
Equals(...)
op_Equality(...)
op_Inequality(...)
op_Equality(...)
op_Inequality(...)
op_Equality(...)
op_Inequality(...)
op_Equality(...)
op_Inequality(...)
op_Equality(...)
op_Inequality(...)
op_Equality(...)
op_Inequality(...)
Equals(...)
GetHashCode()
.ctor(...)
.ctor(...)
MoveNext()
get_Current()
System.Collections.IEnumerator.get_Current()
System.Collections.IEnumerator.Reset()
Dispose()