Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
HeaderDescriptor.cs
Go to the documentation of this file.
3using System.Text;
5
7
8internal readonly struct HeaderDescriptor : IEquatable<HeaderDescriptor>
9{
10 private readonly string _headerName;
11
12 private readonly KnownHeader _knownHeader;
13
14 public string Name => _headerName;
15
17
19 {
20 get
21 {
22 if (_knownHeader != null)
23 {
25 }
26 return HttpHeaderType.Custom;
27 }
28 }
29
31
32 public HeaderDescriptor(KnownHeader knownHeader)
33 {
34 _knownHeader = knownHeader;
35 _headerName = knownHeader.Name;
36 }
37
38 internal HeaderDescriptor(string headerName)
39 {
40 _headerName = headerName;
41 _knownHeader = null;
42 }
43
45 {
46 if (_knownHeader != null)
47 {
48 return _knownHeader == other._knownHeader;
49 }
50 return string.Equals(_headerName, other._headerName, StringComparison.OrdinalIgnoreCase);
51 }
52
53 public override int GetHashCode()
54 {
55 return _knownHeader?.GetHashCode() ?? StringComparer.OrdinalIgnoreCase.GetHashCode(_headerName);
56 }
57
58 public override bool Equals(object obj)
59 {
60 throw new InvalidOperationException();
61 }
62
63 public static bool TryGet(string headerName, out HeaderDescriptor descriptor)
64 {
65 KnownHeader knownHeader = KnownHeaders.TryGetKnownHeader(headerName);
66 if (knownHeader != null)
67 {
68 descriptor = new HeaderDescriptor(knownHeader);
69 return true;
70 }
71 if (!HttpRuleParser.IsToken(headerName))
72 {
73 descriptor = default(HeaderDescriptor);
74 return false;
75 }
76 descriptor = new HeaderDescriptor(headerName);
77 return true;
78 }
79
80 public static bool TryGet(ReadOnlySpan<byte> headerName, out HeaderDescriptor descriptor)
81 {
82 KnownHeader knownHeader = KnownHeaders.TryGetKnownHeader(headerName);
83 if (knownHeader != null)
84 {
85 descriptor = new HeaderDescriptor(knownHeader);
86 return true;
87 }
88 if (!HttpRuleParser.IsToken(headerName))
89 {
90 descriptor = default(HeaderDescriptor);
91 return false;
92 }
93 descriptor = new HeaderDescriptor(HttpRuleParser.GetTokenString(headerName));
94 return true;
95 }
96
97 internal static bool TryGetStaticQPackHeader(int index, out HeaderDescriptor descriptor, [NotNullWhen(true)] out string knownValue)
98 {
100 if ((uint)index < (uint)headerLookup.Length)
101 {
102 (descriptor, knownValue) = headerLookup[index];
103 return true;
104 }
105 descriptor = default(HeaderDescriptor);
106 knownValue = null;
107 return false;
108 }
109
111 {
113 }
114
115 public string GetHeaderValue(ReadOnlySpan<byte> headerValue, Encoding valueEncoding)
116 {
117 if (headerValue.Length == 0)
118 {
119 return string.Empty;
120 }
121 if (_knownHeader != null)
122 {
123 string[] knownValues = _knownHeader.KnownValues;
124 if (knownValues != null)
125 {
126 for (int i = 0; i < knownValues.Length; i++)
127 {
128 if (ByteArrayHelpers.EqualsOrdinalAsciiIgnoreCase(knownValues[i], headerValue))
129 {
130 return knownValues[i];
131 }
132 }
133 }
134 string decoded;
136 {
137 string knownContentType = GetKnownContentType(headerValue);
138 if (knownContentType != null)
139 {
140 return knownContentType;
141 }
142 }
143 else if (_knownHeader == KnownHeaders.Location && TryDecodeUtf8(headerValue, out decoded))
144 {
145 return decoded;
146 }
147 }
148 return (valueEncoding ?? HttpRuleParser.DefaultHttpEncoding).GetString(headerValue);
149 }
150
151 internal static string GetKnownContentType(ReadOnlySpan<byte> contentTypeValue)
152 {
153 string text = null;
154 switch (contentTypeValue.Length)
155 {
156 case 8:
157 switch (contentTypeValue[7] | 0x20)
158 {
159 case 108:
160 text = "text/xml";
161 break;
162 case 115:
163 text = "text/css";
164 break;
165 case 118:
166 text = "text/csv";
167 break;
168 }
169 break;
170 case 9:
171 switch (contentTypeValue[6] | 0x20)
172 {
173 case 103:
174 text = "image/gif";
175 break;
176 case 112:
177 text = "image/png";
178 break;
179 case 116:
180 text = "text/html";
181 break;
182 }
183 break;
184 case 10:
185 switch (contentTypeValue[0] | 0x20)
186 {
187 case 116:
188 text = "text/plain";
189 break;
190 case 105:
191 text = "image/jpeg";
192 break;
193 }
194 break;
195 case 15:
196 switch (contentTypeValue[12] | 0x20)
197 {
198 case 112:
199 text = "application/pdf";
200 break;
201 case 120:
202 text = "application/xml";
203 break;
204 case 122:
205 text = "application/zip";
206 break;
207 }
208 break;
209 case 16:
210 switch (contentTypeValue[12] | 0x20)
211 {
212 case 103:
213 text = "application/grpc";
214 break;
215 case 106:
216 text = "application/json";
217 break;
218 }
219 break;
220 case 19:
221 text = "multipart/form-data";
222 break;
223 case 22:
224 text = "application/javascript";
225 break;
226 case 24:
227 switch (contentTypeValue[0] | 0x20)
228 {
229 case 97:
230 text = "application/octet-stream";
231 break;
232 case 116:
233 text = "text/html; charset=utf-8";
234 break;
235 }
236 break;
237 case 25:
238 text = "text/plain; charset=utf-8";
239 break;
240 case 31:
241 text = "application/json; charset=utf-8";
242 break;
243 case 33:
244 text = "application/x-www-form-urlencoded";
245 break;
246 }
247 if (text == null || !ByteArrayHelpers.EqualsOrdinalAsciiIgnoreCase(text, contentTypeValue))
248 {
249 return null;
250 }
251 return text;
252 }
253
254 private static bool TryDecodeUtf8(ReadOnlySpan<byte> input, [NotNullWhen(true)] out string decoded)
255 {
256 char[] array = ArrayPool<char>.Shared.Rent(input.Length);
257 try
258 {
259 if (Utf8.ToUtf16(input, array, out var _, out var charsWritten, replaceInvalidSequences: false) == OperationStatus.Done)
260 {
261 decoded = new string(array, 0, charsWritten);
262 return true;
263 }
264 }
265 finally
266 {
268 }
269 decoded = null;
270 return false;
271 }
272}
static ArrayPool< T > Shared
Definition ArrayPool.cs:7
static bool EqualsOrdinalAsciiIgnoreCase(string left, ReadOnlySpan< byte > right)
static readonly KnownHeader ContentType
static KnownHeader TryGetKnownHeader(string name)
static readonly KnownHeader Location
static HeaderDescriptor string value[] HeaderLookup
static string GetTokenString(ReadOnlySpan< byte > input)
static bool IsToken(string input)
static Encoding DefaultHttpEncoding
static StringComparer OrdinalIgnoreCase
static unsafe OperationStatus ToUtf16(ReadOnlySpan< byte > source, Span< char > destination, out int bytesRead, out int charsWritten, bool replaceInvalidSequences=true, bool isFinalBlock=true)
Definition Utf8.cs:54
static bool TryGetStaticQPackHeader(int index, out HeaderDescriptor descriptor, [NotNullWhen(true)] out string knownValue)
static bool TryGet(ReadOnlySpan< byte > headerName, out HeaderDescriptor descriptor)
static bool TryGet(string headerName, out HeaderDescriptor descriptor)
static string GetKnownContentType(ReadOnlySpan< byte > contentTypeValue)
static bool TryDecodeUtf8(ReadOnlySpan< byte > input, [NotNullWhen(true)] out string decoded)
string GetHeaderValue(ReadOnlySpan< byte > headerValue, Encoding valueEncoding)
bool Equals(HeaderDescriptor other)