/
TransferCodingHeaderValue.cs
145 lines (117 loc) · 5.15 KB
/
TransferCodingHeaderValue.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Text;
namespace System.Net.Http.Headers
{
public class TransferCodingHeaderValue : ICloneable
{
// Use UnvalidatedObjectCollection<T> since we may have multiple parameters with the same name.
private UnvalidatedObjectCollection<NameValueHeaderValue>? _parameters;
private string _value = null!; // empty constructor only used internally and value set with non null
public string Value => _value;
public ICollection<NameValueHeaderValue> Parameters => _parameters ??= new UnvalidatedObjectCollection<NameValueHeaderValue>();
internal TransferCodingHeaderValue()
{
}
protected TransferCodingHeaderValue(TransferCodingHeaderValue source)
{
Debug.Assert(source != null);
_value = source._value;
_parameters = source._parameters.Clone();
}
public TransferCodingHeaderValue(string value)
{
HeaderUtilities.CheckValidToken(value);
_value = value;
}
public static TransferCodingHeaderValue Parse(string input)
{
int index = 0;
return (TransferCodingHeaderValue)TransferCodingHeaderParser.SingleValueParser.ParseValue(
input, null, ref index);
}
public static bool TryParse([NotNullWhen(true)] string? input, [NotNullWhen(true)] out TransferCodingHeaderValue? parsedValue)
{
int index = 0;
parsedValue = null;
if (TransferCodingHeaderParser.SingleValueParser.TryParseValue(input, null, ref index, out object? output))
{
parsedValue = (TransferCodingHeaderValue)output!;
return true;
}
return false;
}
internal static int GetTransferCodingLength(string input, int startIndex,
Func<TransferCodingHeaderValue> transferCodingCreator, out TransferCodingHeaderValue? parsedValue)
{
Debug.Assert(transferCodingCreator != null);
Debug.Assert(startIndex >= 0);
parsedValue = null;
if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
{
return 0;
}
// Caller must remove leading whitespace. If not, we'll return 0.
int valueLength = HttpRuleParser.GetTokenLength(input, startIndex);
if (valueLength == 0)
{
return 0;
}
string value = input.Substring(startIndex, valueLength);
int current = startIndex + valueLength;
current += HttpRuleParser.GetWhitespaceLength(input, current);
TransferCodingHeaderValue transferCodingHeader;
// If we're not done and we have a parameter delimiter, then we have a list of parameters.
if ((current < input.Length) && (input[current] == ';'))
{
transferCodingHeader = transferCodingCreator();
transferCodingHeader._value = value;
current++; // skip delimiter.
int parameterLength = NameValueHeaderValue.GetNameValueListLength(input, current, ';',
(UnvalidatedObjectCollection<NameValueHeaderValue>)transferCodingHeader.Parameters);
if (parameterLength == 0)
{
return 0;
}
parsedValue = transferCodingHeader;
return current + parameterLength - startIndex;
}
// We have a transfer coding without parameters.
transferCodingHeader = transferCodingCreator();
transferCodingHeader._value = value;
parsedValue = transferCodingHeader;
return current - startIndex;
}
public override string ToString()
{
StringBuilder sb = StringBuilderCache.Acquire();
sb.Append(_value);
NameValueHeaderValue.ToString(_parameters, ';', true, sb);
return StringBuilderCache.GetStringAndRelease(sb);
}
public override bool Equals([NotNullWhen(true)] object? obj)
{
TransferCodingHeaderValue? other = obj as TransferCodingHeaderValue;
if (other == null)
{
return false;
}
return string.Equals(_value, other._value, StringComparison.OrdinalIgnoreCase) &&
HeaderUtilities.AreEqualCollections(_parameters, other._parameters);
}
public override int GetHashCode()
{
// The value string is case-insensitive.
return StringComparer.OrdinalIgnoreCase.GetHashCode(_value) ^ NameValueHeaderValue.GetHashCode(_parameters);
}
// Implement ICloneable explicitly to allow derived types to "override" the implementation.
object ICloneable.Clone()
{
return new TransferCodingHeaderValue(this);
}
}
}