blob: 2f308cbb1120bec13bd6dcb586b0e19c2bebced7 [file] [log] [blame]
Jan Tattermuschc0b37212015-03-13 08:35:41 -07001#region Copyright notice and license
2// Copyright 2015, Google Inc.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30#endregion
31
32using System;
Jan Tattermusche5c9b802015-07-14 17:46:58 -070033using System.Collections;
Jan Tattermuschc0b37212015-03-13 08:35:41 -070034using System.Collections.Generic;
35using System.Collections.Immutable;
Jan Tattermusche5c9b802015-07-14 17:46:58 -070036using System.Collections.Specialized;
Jan Tattermuschc0b37212015-03-13 08:35:41 -070037using System.Runtime.InteropServices;
38using System.Text;
39
Jan Tattermusche5c9b802015-07-14 17:46:58 -070040using Grpc.Core.Utils;
41
Jan Tattermuschc0b37212015-03-13 08:35:41 -070042namespace Grpc.Core
43{
44 /// <summary>
Jan Tattermusche5c9b802015-07-14 17:46:58 -070045 /// Provides access to read and write metadata values to be exchanged during a call.
Jan Tattermuschc0b37212015-03-13 08:35:41 -070046 /// </summary>
Jan Tattermusche5c9b802015-07-14 17:46:58 -070047 public sealed class Metadata : IList<Metadata.Entry>
Jan Tattermuschc0b37212015-03-13 08:35:41 -070048 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -070049 /// <summary>
50 /// An read-only instance of metadata containing no entries.
51 /// </summary>
52 public static readonly Metadata Empty = new Metadata().Freeze();
Jan Tattermuschc0b37212015-03-13 08:35:41 -070053
Jan Tattermusche5c9b802015-07-14 17:46:58 -070054 readonly List<Entry> entries;
55 bool readOnly;
Jan Tattermuschc0b37212015-03-13 08:35:41 -070056
Jan Tattermusche5c9b802015-07-14 17:46:58 -070057 public Metadata()
Jan Tattermuschc0b37212015-03-13 08:35:41 -070058 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -070059 this.entries = new List<Entry>();
Jan Tattermuschc0b37212015-03-13 08:35:41 -070060 }
61
Jan Tattermusche5c9b802015-07-14 17:46:58 -070062 public Metadata(ICollection<Entry> entries)
63 {
64 this.entries = new List<Entry>(entries);
65 }
66
67 /// <summary>
68 /// Makes this object read-only.
69 /// </summary>
70 /// <returns>this object</returns>
71 public Metadata Freeze()
72 {
73 this.readOnly = true;
74 return this;
75 }
76
77 // TODO: add support for access by key
78
79 #region IList members
80
81 public int IndexOf(Metadata.Entry item)
82 {
83 return entries.IndexOf(item);
84 }
85
86 public void Insert(int index, Metadata.Entry item)
87 {
88 CheckWriteable();
89 entries.Insert(index, item);
90 }
91
92 public void RemoveAt(int index)
93 {
94 CheckWriteable();
95 entries.RemoveAt(index);
96 }
97
98 public Metadata.Entry this[int index]
Jan Tattermuschc0b37212015-03-13 08:35:41 -070099 {
100 get
101 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700102 return entries[index];
103 }
104
105 set
106 {
107 CheckWriteable();
108 entries[index] = value;
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700109 }
110 }
111
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700112 public void Add(Metadata.Entry item)
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700113 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700114 CheckWriteable();
115 entries.Add(item);
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700116 }
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700117
118 public void Clear()
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700119 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700120 CheckWriteable();
121 entries.Clear();
122 }
123
124 public bool Contains(Metadata.Entry item)
125 {
126 return entries.Contains(item);
127 }
128
129 public void CopyTo(Metadata.Entry[] array, int arrayIndex)
130 {
131 entries.CopyTo(array, arrayIndex);
132 }
133
134 public int Count
135 {
136 get { return entries.Count; }
137 }
138
139 public bool IsReadOnly
140 {
141 get { return readOnly; }
142 }
143
144 public bool Remove(Metadata.Entry item)
145 {
146 CheckWriteable();
147 return entries.Remove(item);
148 }
149
150 public IEnumerator<Metadata.Entry> GetEnumerator()
151 {
152 return entries.GetEnumerator();
153 }
154
155 IEnumerator System.Collections.IEnumerable.GetEnumerator()
156 {
157 return entries.GetEnumerator();
158 }
159
160 private void CheckWriteable()
161 {
162 Preconditions.CheckState(!readOnly, "Object is read only");
163 }
164
165 #endregion
166
167 /// <summary>
168 /// Metadata entry
169 /// </summary>
170 public struct Entry
171 {
172 private static readonly Encoding Encoding = Encoding.ASCII;
173
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700174 readonly string key;
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700175 string value;
176 byte[] valueBytes;
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700177
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700178 public Entry(string key, byte[] valueBytes)
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700179 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700180 this.key = Preconditions.CheckNotNull(key);
181 this.value = null;
182 this.valueBytes = Preconditions.CheckNotNull(valueBytes);
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700183 }
184
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700185 public Entry(string key, string value)
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700186 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700187 this.key = Preconditions.CheckNotNull(key);
188 this.value = Preconditions.CheckNotNull(value);
189 this.valueBytes = null;
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700190 }
191
192 public string Key
193 {
194 get
195 {
196 return this.key;
197 }
198 }
199
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700200 public byte[] ValueBytes
201 {
202 get
203 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700204 if (valueBytes == null)
205 {
206 valueBytes = Encoding.GetBytes(value);
207 }
208 return valueBytes;
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700209 }
210 }
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700211
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700212 public string Value
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700213 {
214 get
215 {
Jan Tattermusche5c9b802015-07-14 17:46:58 -0700216 if (value == null)
217 {
218 value = Encoding.GetString(valueBytes);
219 }
220 return value;
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700221 }
222 }
Jan Tattermusch998eb9b2015-07-20 22:12:53 -0700223
224 public override string ToString()
225 {
226 return string.Format("[Entry: key={0}, value={1}]", Key, Value);
227 }
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700228 }
Jan Tattermusch55652c72015-07-16 15:03:28 -0700229 }
Jan Tattermuschc0b37212015-03-13 08:35:41 -0700230}