Skip to content

Commit

Permalink
Merge pull request #131 from andreaTP/add-tryadd
Browse files Browse the repository at this point in the history
Add a TryAdd method to Headers
  • Loading branch information
baywet authored Oct 3, 2023
2 parents cd20a6a + f33a7d3 commit 782c4c5
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 31 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.3.4] - 2023-10-04

### Changed

- Added a TryAdd method on the RequestHeaders Dictionary

## [1.3.3] - 2023-09-25

### Changed
Expand Down
69 changes: 53 additions & 16 deletions Microsoft.Kiota.Abstractions.Tests/RequestHeadersTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

namespace Microsoft.Kiota.Abstractions.Tests;

public class RequestHeadersTests {
public class RequestHeadersTests
{
[Fact]
public void Defensive() {
public void Defensive()
{
var instance = new RequestHeaders();
Assert.Throws<ArgumentNullException>(() => instance.Add(null, "value"));
Assert.Throws<ArgumentNullException>(() => instance.Add("name", (string[])null));
Expand All @@ -21,38 +23,69 @@ public void Defensive() {
instance.ContainsKey(null);
}
[Fact]
public void AddsToNonExistent() {
public void AddsToNonExistent()
{
var instance = new RequestHeaders();
instance.Add("name", "value");
Assert.Equal(new [] { "value" }, instance["name"]);
Assert.Equal(new[] { "value" }, instance["name"]);
}
[Fact]
public void AddsToExistent() {
public void TryAddsToNonExistent()
{
var instance = new RequestHeaders();
var result = instance.TryAdd("name", "value");
Assert.True(result);
Assert.Equal(new[] { "value" }, instance["name"]);
}
[Fact]
public void AddsToExistent()
{
var instance = new RequestHeaders();
instance.Add("name", "value");
instance.Add("name", "value2");
Assert.Equal(new [] { "value", "value2" }, instance["name"]);
Assert.Equal(new[] { "value", "value2" }, instance["name"]);
}
[Fact]
public void AddsSingleValueHeaderToExistent() {
public void TryAddsToExistent()
{
var instance = new RequestHeaders();
var result = instance.TryAdd("name", "value");
Assert.True(result);
result = instance.TryAdd("name", "value2");
Assert.False(result);
Assert.Equal(new[] { "value" }, instance["name"]);
}
[Fact]
public void AddsSingleValueHeaderToExistent()
{
var instance = new RequestHeaders();
instance.Add("Content-Type", "value");
instance.Add("Content-Type", "value2");
Assert.Equal(new[] { "value2" }, instance["Content-Type"]);
}
[Fact]
public void RemovesValue() {
public void TryAddsSingleValueHeaderToExistent()
{
var instance = new RequestHeaders();
instance.TryAdd("Content-Type", "value");
instance.TryAdd("Content-Type", "value2");
Assert.Equal(new[] { "value" }, instance["Content-Type"]);
}
[Fact]
public void RemovesValue()
{
var instance = new RequestHeaders();
instance.Remove("name", "value");
instance.Add("name", "value");
instance.Add("name", "value2");
instance.Remove("name", "value");
Assert.Equal(new [] { "value2" }, instance["name"]);
Assert.Equal(new[] { "value2" }, instance["name"]);
instance.Remove("name", "value2");
Assert.Throws<KeyNotFoundException>(() => instance["name"]);
}
[Fact]
public void Removes() {
public void Removes()
{
var instance = new RequestHeaders();
instance.Add("name", "value");
instance.Add("name", "value2");
Expand All @@ -61,16 +94,18 @@ public void Removes() {
Assert.False(instance.Remove("name"));
}
[Fact]
public void RemovesKVP() {
public void RemovesKVP()
{
var instance = new RequestHeaders();
instance.Add("name", "value");
instance.Add("name", "value2");
Assert.True(instance.Remove(new KeyValuePair<string, IEnumerable<string>>("name", new [] { "value", "value2" })));
Assert.True(instance.Remove(new KeyValuePair<string, IEnumerable<string>>("name", new[] { "value", "value2" })));
Assert.Throws<KeyNotFoundException>(() => instance["name"]);
Assert.False(instance.Remove("name"));
}
[Fact]
public void Clears() {
public void Clears()
{
var instance = new RequestHeaders();
instance.Add("name", "value");
instance.Add("name", "value2");
Expand All @@ -79,18 +114,20 @@ public void Clears() {
Assert.Empty(instance.Keys);
}
[Fact]
public void GetsEnumerator() {
public void GetsEnumerator()
{
var instance = new RequestHeaders();
instance.Add("name", "value");
instance.Add("name", "value2");
using var enumerator = instance.GetEnumerator();
Assert.True(enumerator.MoveNext());
Assert.Equal("name", enumerator.Current.Key);
Assert.Equal(new [] { "value", "value2" }, enumerator.Current.Value);
Assert.Equal(new[] { "value", "value2" }, enumerator.Current.Value);
Assert.False(enumerator.MoveNext());
}
[Fact]
public void Updates() {
public void Updates()
{
var instance = new RequestHeaders();
instance.Add("name", "value");
instance.Add("name", "value2");
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.Kiota.Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<PackageProjectUrl>https://aka.ms/kiota/docs</PackageProjectUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<Deterministic>true</Deterministic>
<VersionPrefix>1.3.3</VersionPrefix>
<VersionPrefix>1.3.4</VersionPrefix>
<VersionSuffix></VersionSuffix>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<SignAssembly>false</SignAssembly>
Expand Down
59 changes: 45 additions & 14 deletions src/RequestHeaders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
namespace Microsoft.Kiota.Abstractions;

/// <summary>Represents a collection of request headers.</summary>
public class RequestHeaders : IDictionary<string,IEnumerable<string>> {
public class RequestHeaders : IDictionary<string, IEnumerable<string>>
{
private readonly Dictionary<string, HashSet<string>> _headers = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase);
private readonly HashSet<string> _singleValueHeaders = new HashSet<string>(StringComparer.OrdinalIgnoreCase) {
"Content-Type",
Expand All @@ -18,7 +19,8 @@ public class RequestHeaders : IDictionary<string,IEnumerable<string>> {
/// </summary>
/// <param name="headerName">The name of the header to add values to.</param>
/// <param name="headerValues">The values to add to the header.</param>
public void Add(string headerName, params string[] headerValues) {
public void Add(string headerName, params string[] headerValues)
{
if(string.IsNullOrEmpty(headerName))
throw new ArgumentNullException(nameof(headerName));
if(headerValues == null)
Expand All @@ -33,6 +35,25 @@ public void Add(string headerName, params string[] headerValues) {
else
_headers.Add(headerName, new HashSet<string>(headerValues));
}
/// <summary>
/// Adds values to the header with the specified name if it's not already present
/// </summary>
/// <param name="headerName">The name of the header to add values to.</param>
/// <param name="headerValue">The values to add to the header.</param>
/// <returns>If the headerValue have been added to the Dictionary.</returns>
public bool TryAdd(string headerName, string headerValue)
{
if(string.IsNullOrEmpty(headerName))
throw new ArgumentNullException(nameof(headerName));
if(headerValue == null)
throw new ArgumentNullException(nameof(headerValue));
if(!_headers.ContainsKey(headerName))
{
_headers.Add(headerName, new HashSet<string> { headerValue });
return true;
}
return false;
}
/// <inheritdoc/>
public ICollection<string> Keys => _headers.Keys;
/// <inheritdoc/>
Expand All @@ -49,14 +70,16 @@ public void Add(string headerName, params string[] headerValues) {
/// </summary>
/// <param name="headerName">The name of the header to remove the value from.</param>
/// <param name="headerValue">The value to remove from the header.</param>
public bool Remove(string headerName, string headerValue) {
public bool Remove(string headerName, string headerValue)
{
if(string.IsNullOrEmpty(headerName))
throw new ArgumentNullException(nameof(headerName));
if(headerValue == null)
throw new ArgumentNullException(nameof(headerValue));
if(_headers.TryGetValue(headerName, out var values)) {
if(_headers.TryGetValue(headerName, out var values))
{
var result = values.Remove(headerValue);
if (!values.Any())
if(!values.Any())
_headers.Remove(headerName);
return result;
}
Expand All @@ -66,7 +89,8 @@ public bool Remove(string headerName, string headerValue) {
/// Adds all the headers values from the specified headers collection.
/// </summary>
/// <param name="headers">The headers to update the current headers with.</param>
public void AddAll(RequestHeaders headers) {
public void AddAll(RequestHeaders headers)
{
if(headers == null)
throw new ArgumentNullException(nameof(headers));
foreach(var header in headers)
Expand All @@ -76,7 +100,8 @@ public void AddAll(RequestHeaders headers) {
/// <summary>
/// Removes all headers.
/// </summary>
public void Clear() {
public void Clear()
{
_headers.Clear();
}
/// <inheritdoc/>
Expand All @@ -86,16 +111,19 @@ public void Clear() {
public void Add(string key, IEnumerable<string> value) => Add(key, value?.ToArray());
#pragma warning restore CS8604 // Possible null reference argument.
/// <inheritdoc/>
public bool Remove(string key) {
public bool Remove(string key)
{
if(string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
return _headers.Remove(key);
}
/// <inheritdoc/>
public bool TryGetValue(string key, out IEnumerable<string> value) {
public bool TryGetValue(string key, out IEnumerable<string> value)
{
if(string.IsNullOrEmpty(key))
throw new ArgumentNullException(nameof(key));
if(_headers.TryGetValue(key, out var values)) {
if(_headers.TryGetValue(key, out var values))
{
value = values;
return true;
}
Expand All @@ -109,16 +137,18 @@ public bool TryGetValue(string key, out IEnumerable<string> value) {
/// <inheritdoc/>
public void CopyTo(KeyValuePair<string, IEnumerable<string>>[] array, int arrayIndex) => throw new NotImplementedException();
/// <inheritdoc/>
public bool Remove(KeyValuePair<string, IEnumerable<string>> item) {
public bool Remove(KeyValuePair<string, IEnumerable<string>> item)
{
var result = false;
foreach (var value in item.Value)
foreach(var value in item.Value)
result |= Remove(item.Key, value);
return result;
}
/// <inheritdoc/>
public IEnumerator<KeyValuePair<string, IEnumerable<string>>> GetEnumerator() => new RequestHeadersEnumerator(_headers.GetEnumerator());
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
private sealed class RequestHeadersEnumerator : IEnumerator<KeyValuePair<string, IEnumerable<string>>> {
private sealed class RequestHeadersEnumerator : IEnumerator<KeyValuePair<string, IEnumerable<string>>>
{
private readonly IEnumerator _enumerator;
public RequestHeadersEnumerator(IEnumerator enumerator)
{
Expand All @@ -128,7 +158,8 @@ public RequestHeadersEnumerator(IEnumerator enumerator)

object IEnumerator.Current => Current;

public void Dispose() {
public void Dispose()
{
(_enumerator as IDisposable)?.Dispose();
GC.SuppressFinalize(this);
}
Expand Down

0 comments on commit 782c4c5

Please sign in to comment.