|
| 1 | +using System; |
| 2 | +using System.Collections; |
| 3 | +using System.Collections.Generic; |
| 4 | +using System.Linq; |
| 5 | + |
| 6 | +namespace Microsoft.Kiota.Abstractions; |
| 7 | + |
| 8 | +/// <summary>Represents a collection of request headers.</summary> |
| 9 | +public class RequestHeaders : IDictionary<string,IEnumerable<string>> { |
| 10 | + private readonly Dictionary<string, HashSet<string>> _headers = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase); |
| 11 | + /// <summary> |
| 12 | + /// Adds values to the header with the specified name. |
| 13 | + /// </summary> |
| 14 | + /// <param name="headerName">The name of the header to add values to.</param> |
| 15 | + /// <param name="headerValues">The values to add to the header.</param> |
| 16 | + public void Add(string headerName, params string[] headerValues) { |
| 17 | + if(string.IsNullOrEmpty(headerName)) |
| 18 | + throw new ArgumentNullException(nameof(headerName)); |
| 19 | + if(headerValues == null) |
| 20 | + throw new ArgumentNullException(nameof(headerValues)); |
| 21 | + if(!headerValues.Any()) |
| 22 | + return; |
| 23 | + if(_headers.TryGetValue(headerName, out var values)) |
| 24 | + foreach(var headerValue in headerValues) |
| 25 | + values.Add(headerValue); |
| 26 | + else |
| 27 | + _headers.Add(headerName, new HashSet<string>(headerValues)); |
| 28 | + } |
| 29 | + /// <inheritdoc/> |
| 30 | + public ICollection<string> Keys => _headers.Keys; |
| 31 | + /// <inheritdoc/> |
| 32 | + public ICollection<IEnumerable<string>> Values => _headers.Values.Cast<IEnumerable<string>>().ToList(); |
| 33 | + /// <inheritdoc/> |
| 34 | + public int Count => _headers.Count; |
| 35 | + /// <inheritdoc/> |
| 36 | + public bool IsReadOnly => false; |
| 37 | + /// <inheritdoc/> |
| 38 | + public IEnumerable<string> this[string key] { get => TryGetValue(key, out var result) ? result : null; set => Add(key, value); } |
| 39 | + |
| 40 | + /// <summary> |
| 41 | + /// Removes the specified value from the header with the specified name. |
| 42 | + /// </summary> |
| 43 | + /// <param name="headerName">The name of the header to remove the value from.</param> |
| 44 | + /// <param name="headerValue">The value to remove from the header.</param> |
| 45 | + public bool Remove(string headerName, string headerValue) { |
| 46 | + if(string.IsNullOrEmpty(headerName)) |
| 47 | + throw new ArgumentNullException(nameof(headerName)); |
| 48 | + if(headerValue == null) |
| 49 | + throw new ArgumentNullException(nameof(headerValue)); |
| 50 | + if(_headers.TryGetValue(headerName, out var values)) { |
| 51 | + var result = values.Remove(headerValue); |
| 52 | + if (!values.Any()) |
| 53 | + _headers.Remove(headerName); |
| 54 | + return result; |
| 55 | + } |
| 56 | + return false; |
| 57 | + } |
| 58 | + /// <summary> |
| 59 | + /// Adds all the headers values from the specified headers collection. |
| 60 | + /// </summary> |
| 61 | + /// <param name="headers">The headers to update the current headers with.</param> |
| 62 | + public void AddAll(RequestHeaders headers) { |
| 63 | + if(headers == null) |
| 64 | + throw new ArgumentNullException(nameof(headers)); |
| 65 | + foreach(var header in headers) |
| 66 | + foreach(var value in header.Value) |
| 67 | + Add(header.Key, value); |
| 68 | + } |
| 69 | + /// <summary> |
| 70 | + /// Removes all headers. |
| 71 | + /// </summary> |
| 72 | + public void Clear() { |
| 73 | + _headers.Clear(); |
| 74 | + } |
| 75 | + /// <inheritdoc/> |
| 76 | + public bool ContainsKey(string key) => !string.IsNullOrEmpty(key) && _headers.ContainsKey(key); |
| 77 | + /// <inheritdoc/> |
| 78 | + public void Add(string key, IEnumerable<string> value) => Add(key, value?.ToArray()); |
| 79 | + /// <inheritdoc/> |
| 80 | + public bool Remove(string key) { |
| 81 | + if(string.IsNullOrEmpty(key)) |
| 82 | + throw new ArgumentNullException(nameof(key)); |
| 83 | + return _headers.Remove(key); |
| 84 | + } |
| 85 | + /// <inheritdoc/> |
| 86 | + public bool TryGetValue(string key, out IEnumerable<string> value) { |
| 87 | + if(string.IsNullOrEmpty(key)) |
| 88 | + throw new ArgumentNullException(nameof(key)); |
| 89 | + if(_headers.TryGetValue(key, out var values)) { |
| 90 | + value = values; |
| 91 | + return true; |
| 92 | + } |
| 93 | + value = Enumerable.Empty<string>(); |
| 94 | + return false; |
| 95 | + } |
| 96 | + /// <inheritdoc/> |
| 97 | + public void Add(KeyValuePair<string, IEnumerable<string>> item) => Add(item.Key, item.Value); |
| 98 | + /// <inheritdoc/> |
| 99 | + public bool Contains(KeyValuePair<string, IEnumerable<string>> item) => TryGetValue(item.Key, out var values) && item.Value.All(x => values.Contains(x)) && values.Count() == item.Value.Count(); |
| 100 | + /// <inheritdoc/> |
| 101 | + public void CopyTo(KeyValuePair<string, IEnumerable<string>>[] array, int arrayIndex) => throw new NotImplementedException(); |
| 102 | + /// <inheritdoc/> |
| 103 | + public bool Remove(KeyValuePair<string, IEnumerable<string>> item) { |
| 104 | + var result = false; |
| 105 | + foreach (var value in item.Value) |
| 106 | + result |= Remove(item.Key, value); |
| 107 | + return result; |
| 108 | + } |
| 109 | + /// <inheritdoc/> |
| 110 | + public IEnumerator<KeyValuePair<string, IEnumerable<string>>> GetEnumerator() => new RequestHeadersEnumerator(_headers.GetEnumerator()); |
| 111 | + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); |
| 112 | + private sealed class RequestHeadersEnumerator : IEnumerator<KeyValuePair<string, IEnumerable<string>>> { |
| 113 | + private readonly IEnumerator _enumerator; |
| 114 | + public RequestHeadersEnumerator(IEnumerator enumerator) |
| 115 | + { |
| 116 | + _enumerator = enumerator; |
| 117 | + } |
| 118 | + public KeyValuePair<string, IEnumerable<string>> Current => _enumerator.Current is KeyValuePair<string, HashSet<string>> current ? new(current.Key, current.Value) : throw new InvalidOperationException(); |
| 119 | + |
| 120 | + object IEnumerator.Current => Current; |
| 121 | + |
| 122 | + public void Dispose() { |
| 123 | + (_enumerator as IDisposable)?.Dispose(); |
| 124 | + GC.SuppressFinalize(this); |
| 125 | + } |
| 126 | + public bool MoveNext() => _enumerator.MoveNext(); |
| 127 | + public void Reset() => _enumerator.Reset(); |
| 128 | + } |
| 129 | +} |
0 commit comments