@@ -6617,7 +6617,7 @@ public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
6617
6617
ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
6618
6618
var flag = 0L;
6619
6619
6620
- // Does the name matched any "known" headers
6620
+ // Does the name match any "known" headers
6621
6621
switch (name.Length)
6622
6622
{
6623
6623
case 2:
@@ -7070,6 +7070,251 @@ public unsafe void Append(ReadOnlySpan<byte> name, ReadOnlySpan<byte> value)
7070
7070
}
7071
7071
}
7072
7072
7073
+ [MethodImpl(MethodImplOptions.AggressiveOptimization)]
7074
+ public unsafe bool TryHPackAppend(int index, ReadOnlySpan<byte> value)
7075
+ {
7076
+ ref StringValues values = ref Unsafe.AsRef<StringValues>(null);
7077
+ var nameStr = string.Empty;
7078
+ var flag = 0L;
7079
+
7080
+ // Does the HPack static index match any "known" headers
7081
+ switch (index)
7082
+ {
7083
+ case 1:
7084
+ flag = 0x100000L;
7085
+ values = ref _headers._Authority;
7086
+ nameStr = HeaderNames.Authority;
7087
+ break;
7088
+ case 2:
7089
+ case 3:
7090
+ flag = 0x200000L;
7091
+ values = ref _headers._Method;
7092
+ nameStr = HeaderNames.Method;
7093
+ break;
7094
+ case 4:
7095
+ case 5:
7096
+ flag = 0x400000L;
7097
+ values = ref _headers._Path;
7098
+ nameStr = HeaderNames.Path;
7099
+ break;
7100
+ case 6:
7101
+ case 7:
7102
+ flag = 0x800000L;
7103
+ values = ref _headers._Scheme;
7104
+ nameStr = HeaderNames.Scheme;
7105
+ break;
7106
+ case 15:
7107
+ flag = 0x2000000L;
7108
+ values = ref _headers._AcceptCharset;
7109
+ nameStr = HeaderNames.AcceptCharset;
7110
+ break;
7111
+ case 16:
7112
+ flag = 0x4000000L;
7113
+ values = ref _headers._AcceptEncoding;
7114
+ nameStr = HeaderNames.AcceptEncoding;
7115
+ break;
7116
+ case 17:
7117
+ flag = 0x8000000L;
7118
+ values = ref _headers._AcceptLanguage;
7119
+ nameStr = HeaderNames.AcceptLanguage;
7120
+ break;
7121
+ case 19:
7122
+ flag = 0x1000000L;
7123
+ values = ref _headers._Accept;
7124
+ nameStr = HeaderNames.Accept;
7125
+ break;
7126
+ case 22:
7127
+ flag = 0x800L;
7128
+ values = ref _headers._Allow;
7129
+ nameStr = HeaderNames.Allow;
7130
+ break;
7131
+ case 23:
7132
+ flag = 0x10000000L;
7133
+ values = ref _headers._Authorization;
7134
+ nameStr = HeaderNames.Authorization;
7135
+ break;
7136
+ case 24:
7137
+ flag = 0x1L;
7138
+ values = ref _headers._CacheControl;
7139
+ nameStr = HeaderNames.CacheControl;
7140
+ break;
7141
+ case 26:
7142
+ flag = 0x2000L;
7143
+ values = ref _headers._ContentEncoding;
7144
+ nameStr = HeaderNames.ContentEncoding;
7145
+ break;
7146
+ case 27:
7147
+ flag = 0x4000L;
7148
+ values = ref _headers._ContentLanguage;
7149
+ nameStr = HeaderNames.ContentLanguage;
7150
+ break;
7151
+ case 28:
7152
+ if (ReferenceEquals(EncodingSelector, KestrelServerOptions.DefaultRequestHeaderEncodingSelector))
7153
+ {
7154
+ AppendContentLength(value);
7155
+ }
7156
+ else
7157
+ {
7158
+ AppendContentLengthCustomEncoding(value, EncodingSelector(HeaderNames.ContentLength));
7159
+ }
7160
+ return true;
7161
+ case 29:
7162
+ flag = 0x8000L;
7163
+ values = ref _headers._ContentLocation;
7164
+ nameStr = HeaderNames.ContentLocation;
7165
+ break;
7166
+ case 30:
7167
+ flag = 0x20000L;
7168
+ values = ref _headers._ContentRange;
7169
+ nameStr = HeaderNames.ContentRange;
7170
+ break;
7171
+ case 31:
7172
+ flag = 0x1000L;
7173
+ values = ref _headers._ContentType;
7174
+ nameStr = HeaderNames.ContentType;
7175
+ break;
7176
+ case 32:
7177
+ flag = 0x20000000L;
7178
+ values = ref _headers._Cookie;
7179
+ nameStr = HeaderNames.Cookie;
7180
+ break;
7181
+ case 33:
7182
+ flag = 0x4L;
7183
+ values = ref _headers._Date;
7184
+ nameStr = HeaderNames.Date;
7185
+ break;
7186
+ case 35:
7187
+ flag = 0x40000000L;
7188
+ values = ref _headers._Expect;
7189
+ nameStr = HeaderNames.Expect;
7190
+ break;
7191
+ case 36:
7192
+ flag = 0x40000L;
7193
+ values = ref _headers._Expires;
7194
+ nameStr = HeaderNames.Expires;
7195
+ break;
7196
+ case 37:
7197
+ flag = 0x80000000L;
7198
+ values = ref _headers._From;
7199
+ nameStr = HeaderNames.From;
7200
+ break;
7201
+ case 38:
7202
+ flag = 0x400000000L;
7203
+ values = ref _headers._Host;
7204
+ nameStr = HeaderNames.Host;
7205
+ break;
7206
+ case 39:
7207
+ flag = 0x800000000L;
7208
+ values = ref _headers._IfMatch;
7209
+ nameStr = HeaderNames.IfMatch;
7210
+ break;
7211
+ case 40:
7212
+ flag = 0x1000000000L;
7213
+ values = ref _headers._IfModifiedSince;
7214
+ nameStr = HeaderNames.IfModifiedSince;
7215
+ break;
7216
+ case 41:
7217
+ flag = 0x2000000000L;
7218
+ values = ref _headers._IfNoneMatch;
7219
+ nameStr = HeaderNames.IfNoneMatch;
7220
+ break;
7221
+ case 42:
7222
+ flag = 0x4000000000L;
7223
+ values = ref _headers._IfRange;
7224
+ nameStr = HeaderNames.IfRange;
7225
+ break;
7226
+ case 43:
7227
+ flag = 0x8000000000L;
7228
+ values = ref _headers._IfUnmodifiedSince;
7229
+ nameStr = HeaderNames.IfUnmodifiedSince;
7230
+ break;
7231
+ case 44:
7232
+ flag = 0x80000L;
7233
+ values = ref _headers._LastModified;
7234
+ nameStr = HeaderNames.LastModified;
7235
+ break;
7236
+ case 47:
7237
+ flag = 0x10000000000L;
7238
+ values = ref _headers._MaxForwards;
7239
+ nameStr = HeaderNames.MaxForwards;
7240
+ break;
7241
+ case 49:
7242
+ flag = 0x20000000000L;
7243
+ values = ref _headers._ProxyAuthorization;
7244
+ nameStr = HeaderNames.ProxyAuthorization;
7245
+ break;
7246
+ case 50:
7247
+ flag = 0x80000000000L;
7248
+ values = ref _headers._Range;
7249
+ nameStr = HeaderNames.Range;
7250
+ break;
7251
+ case 51:
7252
+ flag = 0x40000000000L;
7253
+ values = ref _headers._Referer;
7254
+ nameStr = HeaderNames.Referer;
7255
+ break;
7256
+ case 57:
7257
+ flag = 0x80L;
7258
+ values = ref _headers._TransferEncoding;
7259
+ nameStr = HeaderNames.TransferEncoding;
7260
+ break;
7261
+ case 58:
7262
+ flag = 0x400000000000L;
7263
+ values = ref _headers._UserAgent;
7264
+ nameStr = HeaderNames.UserAgent;
7265
+ break;
7266
+ case 60:
7267
+ flag = 0x200L;
7268
+ values = ref _headers._Via;
7269
+ nameStr = HeaderNames.Via;
7270
+ break;
7271
+ }
7272
+
7273
+ if (flag != 0)
7274
+ {
7275
+ // Matched a known header
7276
+ if ((_previousBits & flag) != 0)
7277
+ {
7278
+ // Had a previous string for this header, mark it as used so we don't clear it OnHeadersComplete or consider it if we get a second header
7279
+ _previousBits ^= flag;
7280
+
7281
+ // We will only reuse this header if there was only one previous header
7282
+ if (values.Count == 1)
7283
+ {
7284
+ var previousValue = values.ToString();
7285
+ // Check lengths are the same, then if the bytes were converted to an ascii string if they would be the same.
7286
+ // We do not consider Utf8 headers for reuse.
7287
+ if (previousValue.Length == value.Length &&
7288
+ StringUtilities.BytesOrdinalEqualsStringAndAscii(previousValue, value))
7289
+ {
7290
+ // The previous string matches what the bytes would convert to, so we will just use that one.
7291
+ _bits |= flag;
7292
+ return true;
7293
+ }
7294
+ }
7295
+ }
7296
+
7297
+ // We didn't have a previous matching header value, or have already added a header, so get the string for this value.
7298
+ var valueStr = value.GetRequestHeaderString(nameStr, EncodingSelector);
7299
+ if ((_bits & flag) == 0)
7300
+ {
7301
+ // We didn't already have a header set, so add a new one.
7302
+ _bits |= flag;
7303
+ values = new StringValues(valueStr);
7304
+ }
7305
+ else
7306
+ {
7307
+ // We already had a header set, so concatenate the new one.
7308
+ values = AppendValue(values, valueStr);
7309
+ }
7310
+ return true;
7311
+ }
7312
+ else
7313
+ {
7314
+ return false;
7315
+ }
7316
+ }
7317
+
7073
7318
private struct HeaderReferences
7074
7319
{
7075
7320
public StringValues _CacheControl;
@@ -13716,4 +13961,4 @@ public bool MoveNext()
13716
13961
}
13717
13962
}
13718
13963
}
13719
- }
13964
+ }
0 commit comments