Skip to content

Commit 71a22ca

Browse files
authored
Merge pull request grpc#22743 from JamesNK/jamesnk/metadata-helpers
Add helper methods for getting metadata values
2 parents de8aa7e + bba2a77 commit 71a22ca

File tree

2 files changed

+175
-18
lines changed

2 files changed

+175
-18
lines changed

src/csharp/Grpc.Core.Api/Metadata.cs

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,72 @@ internal Metadata Freeze()
7575
return this;
7676
}
7777

78-
// TODO: add support for access by key
78+
/// <summary>
79+
/// Gets the last metadata entry with the specified key.
80+
/// If there are no matching entries then <c>null</c> is returned.
81+
/// </summary>
82+
public Entry Get(string key)
83+
{
84+
for (int i = entries.Count - 1; i >= 0; i--)
85+
{
86+
if (entries[i].Key == key)
87+
{
88+
return entries[i];
89+
}
90+
}
91+
92+
return null;
93+
}
94+
95+
/// <summary>
96+
/// Gets the string value of the last metadata entry with the specified key.
97+
/// If the metadata entry is binary then an exception is thrown.
98+
/// If there are no matching entries then <c>null</c> is returned.
99+
/// </summary>
100+
public string GetValue(string key)
101+
{
102+
return Get(key)?.Value;
103+
}
104+
105+
/// <summary>
106+
/// Gets the bytes value of the last metadata entry with the specified key.
107+
/// If the metadata entry is not binary the string value will be returned as ASCII encoded bytes.
108+
/// If there are no matching entries then <c>null</c> is returned.
109+
/// </summary>
110+
public byte[] GetValueBytes(string key)
111+
{
112+
return Get(key)?.ValueBytes;
113+
}
114+
115+
/// <summary>
116+
/// Gets all metadata entries with the specified key.
117+
/// </summary>
118+
public IEnumerable<Entry> GetAll(string key)
119+
{
120+
for (int i = 0; i < entries.Count; i++)
121+
{
122+
if (entries[i].Key == key)
123+
{
124+
yield return entries[i];
125+
}
126+
}
127+
}
128+
129+
/// <summary>
130+
/// Adds a new ASCII-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
131+
/// </summary>
132+
public void Add(string key, string value)
133+
{
134+
Add(new Entry(key, value));
135+
}
136+
137+
/// <summary>
138+
/// Adds a new binary-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
139+
/// </summary>
140+
public void Add(string key, byte[] valueBytes)
141+
{
142+
Add(new Entry(key, valueBytes));
143+
}
79144

80145
#region IList members
81146

@@ -135,22 +200,6 @@ public void Add(Metadata.Entry item)
135200
entries.Add(item);
136201
}
137202

138-
/// <summary>
139-
/// Adds a new ASCII-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
140-
/// </summary>
141-
public void Add(string key, string value)
142-
{
143-
Add(new Entry(key, value));
144-
}
145-
146-
/// <summary>
147-
/// Adds a new binary-valued metadata entry. See <c>Metadata.Entry</c> constructor for params.
148-
/// </summary>
149-
public void Add(string key, byte[] valueBytes)
150-
{
151-
Add(new Entry(key, valueBytes));
152-
}
153-
154203
/// <summary>
155204
/// <see cref="T:IList`1"/>
156205
/// </summary>
@@ -280,6 +329,7 @@ public string Key
280329

281330
/// <summary>
282331
/// Gets the binary value of this metadata entry.
332+
/// If the metadata entry is not binary the string value will be returned as ASCII encoded bytes.
283333
/// </summary>
284334
public byte[] ValueBytes
285335
{
@@ -299,13 +349,14 @@ public byte[] ValueBytes
299349

300350
/// <summary>
301351
/// Gets the string value of this metadata entry.
352+
/// If the metadata entry is binary then an exception is thrown.
302353
/// </summary>
303354
public string Value
304355
{
305356
get
306357
{
307358
GrpcPreconditions.CheckState(!IsBinary, "Cannot access string value of a binary metadata entry");
308-
return value ?? EncodingASCII.GetString(valueBytes);
359+
return value;
309360
}
310361
}
311362

src/csharp/Grpc.Core.Tests/MetadataTest.cs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@
1818

1919
using System;
2020
using System.Diagnostics;
21+
using System.Linq;
2122
using System.Runtime.InteropServices;
23+
using System.Text;
2224
using System.Threading;
2325
using System.Threading.Tasks;
2426
using Grpc.Core;
@@ -242,6 +244,110 @@ public void FreezeMakesReadOnly()
242244
Assert.Throws<InvalidOperationException>(() => metadata.Remove(metadata[0]));
243245
}
244246

247+
[Test]
248+
public void GetAll()
249+
{
250+
var metadata = new Metadata
251+
{
252+
{ "abc", "abc-value1" },
253+
{ "abc", "abc-value2" },
254+
{ "xyz", "xyz-value1" },
255+
};
256+
257+
var abcEntries = metadata.GetAll("abc").ToList();
258+
Assert.AreEqual(2, abcEntries.Count);
259+
Assert.AreEqual("abc-value1", abcEntries[0].Value);
260+
Assert.AreEqual("abc-value2", abcEntries[1].Value);
261+
262+
var xyzEntries = metadata.GetAll("xyz").ToList();
263+
Assert.AreEqual(1, xyzEntries.Count);
264+
Assert.AreEqual("xyz-value1", xyzEntries[0].Value);
265+
}
266+
267+
[Test]
268+
public void Get()
269+
{
270+
var metadata = new Metadata
271+
{
272+
{ "abc", "abc-value1" },
273+
{ "abc", "abc-value2" },
274+
{ "xyz", "xyz-value1" },
275+
};
276+
277+
var abcEntry = metadata.Get("abc");
278+
Assert.AreEqual("abc-value2", abcEntry.Value);
279+
280+
var xyzEntry = metadata.Get("xyz");
281+
Assert.AreEqual("xyz-value1", xyzEntry.Value);
282+
283+
var notFound = metadata.Get("not-found");
284+
Assert.AreEqual(null, notFound);
285+
}
286+
287+
[Test]
288+
public void GetValue()
289+
{
290+
var metadata = new Metadata
291+
{
292+
{ "abc", "abc-value1" },
293+
{ "abc", "abc-value2" },
294+
{ "xyz", "xyz-value1" },
295+
{ "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") },
296+
};
297+
298+
var abcValue = metadata.GetValue("abc");
299+
Assert.AreEqual("abc-value2", abcValue);
300+
301+
var xyzValue = metadata.GetValue("xyz");
302+
Assert.AreEqual("xyz-value1", xyzValue);
303+
304+
var notFound = metadata.GetValue("not-found");
305+
Assert.AreEqual(null, notFound);
306+
}
307+
308+
[Test]
309+
public void GetValue_BytesValue()
310+
{
311+
var metadata = new Metadata
312+
{
313+
{ "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") },
314+
};
315+
316+
Assert.Throws<InvalidOperationException>(() => metadata.GetValue("xyz-bin"));
317+
}
318+
319+
[Test]
320+
public void GetValueBytes()
321+
{
322+
var metadata = new Metadata
323+
{
324+
{ "abc-bin", Encoding.ASCII.GetBytes("abc-value1") },
325+
{ "abc-bin", Encoding.ASCII.GetBytes("abc-value2") },
326+
{ "xyz-bin", Encoding.ASCII.GetBytes("xyz-value1") },
327+
};
328+
329+
var abcValue = metadata.GetValueBytes("abc-bin");
330+
Assert.AreEqual(Encoding.ASCII.GetBytes("abc-value2"), abcValue);
331+
332+
var xyzValue = metadata.GetValueBytes("xyz-bin");
333+
Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzValue);
334+
335+
var notFound = metadata.GetValueBytes("not-found");
336+
Assert.AreEqual(null, notFound);
337+
}
338+
339+
[Test]
340+
public void GetValueBytes_StringValue()
341+
{
342+
var metadata = new Metadata
343+
{
344+
{ "xyz", "xyz-value1" },
345+
};
346+
347+
var xyzValue = metadata.GetValueBytes("xyz");
348+
Assert.AreEqual(Encoding.ASCII.GetBytes("xyz-value1"), xyzValue);
349+
}
350+
245351
private Metadata CreateMetadata()
246352
{
247353
return new Metadata

0 commit comments

Comments
 (0)