Url
Represents an Url class according to RFC3986. This is the base for all
internal Url manipulation.
Specification for the API used from https://url.spec.whatwg.org/#api.
using AngleSharp.Attributes;
using AngleSharp.Io;
using AngleSharp.Text;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
namespace AngleSharp.Dom
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
[DomName("URL")]
[DomExposed("Window")]
[DomExposed("Worker")]
public sealed class Url : IEquatable<Url>
{
private static readonly string CurrentDirectory = ".";
private static readonly string CurrentDirectoryAlternative = "%2e";
private static readonly string UpperDirectory = "..";
private static readonly string[] UpperDirectoryAlternatives = new string[3] {
"%2e%2e",
".%2e",
"%2e."
};
private static readonly Url DefaultBase = new Url(string.Empty, string.Empty, string.Empty);
private static readonly char[] C0ControlAndSpace = (from c in Enumerable.Range(0, 33)
select (char)c).ToArray();
private static readonly IdnMapping DefaultIdnMapping = new IdnMapping {
AllowUnassigned = false,
UseStd3AsciiRules = false
};
[System.Runtime.CompilerServices.Nullable(2)]
private string _fragment;
[System.Runtime.CompilerServices.Nullable(2)]
private string _query;
private string _path;
private string _scheme;
private string _port;
private string _host;
[System.Runtime.CompilerServices.Nullable(2)]
private string _username;
[System.Runtime.CompilerServices.Nullable(2)]
private string _password;
private bool _relative;
private string _schemeData;
[System.Runtime.CompilerServices.Nullable(2)]
private UrlSearchParams _params;
private bool _error;
[System.Runtime.CompilerServices.Nullable(2)]
[DomName("origin")]
public string Origin {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
if (_scheme.Is(ProtocolNames.Blob)) {
Url url = new Url(_schemeData);
if (!url.IsInvalid)
return url.Origin;
} else if (ProtocolNames.IsOriginable(_scheme)) {
StringBuilder stringBuilder = StringBuilderPool.Obtain();
if (!string.IsNullOrEmpty(_host)) {
if (!string.IsNullOrEmpty(_scheme))
stringBuilder.Append(_scheme).Append(':');
stringBuilder.Append('/').Append('/').Append(_host);
if (!string.IsNullOrEmpty(_port))
stringBuilder.Append(':').Append(_port);
}
return stringBuilder.ToPool();
}
return null;
}
}
public bool IsInvalid => _error;
public bool IsRelative {
get {
if (_relative)
return string.IsNullOrEmpty(_scheme);
return false;
}
}
public bool IsAbsolute => !IsRelative;
[System.Runtime.CompilerServices.Nullable(2)]
[DomName("username")]
public string UserName {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _username ?? string.Empty;
}
[System.Runtime.CompilerServices.NullableContext(2)]
set {
_username = value;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
[DomName("password")]
public string Password {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _password ?? string.Empty;
}
[System.Runtime.CompilerServices.NullableContext(2)]
set {
_password = value;
}
}
public string Data => _schemeData;
[System.Runtime.CompilerServices.Nullable(2)]
public string Fragment {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _fragment;
}
[System.Runtime.CompilerServices.NullableContext(2)]
set {
if (value == null)
_fragment = null;
else
ParseFragment(value, 0, value.Length);
}
}
[DomName("hash")]
public string Hash {
get {
if (!string.IsNullOrEmpty(_fragment))
return "#" + _fragment;
return string.Empty;
}
set {
if (string.IsNullOrEmpty(value))
Fragment = null;
else if (value[0] == '#') {
Fragment = value.Substring(1);
} else {
Fragment = value;
}
}
}
[DomName("host")]
public string Host {
get {
return HostName + (string.IsNullOrEmpty(_port) ? string.Empty : (":" + _port));
}
set {
string text = value ?? string.Empty;
ParseHostName(text, 0, text.Length, false, true);
}
}
[DomName("hostname")]
public string HostName {
get {
return _host;
}
set {
string text = value ?? string.Empty;
ParseHostName(text, 0, text.Length, true, false);
}
}
[DomName("href")]
public string Href {
get {
return Serialize();
}
set {
_error = ParseUrl(value ?? string.Empty, this);
}
}
public string Path {
get {
return _path;
}
set {
string text = value ?? string.Empty;
ParsePath(text, 0, text.Length, true);
}
}
[DomName("pathname")]
public string PathName {
get {
return "/" + _path;
}
set {
Path = value;
}
}
[DomName("port")]
public string Port {
get {
return _port;
}
set {
string text = value ?? string.Empty;
ParsePort(text, 0, text.Length, true);
}
}
public string Scheme {
get {
return _scheme;
}
set {
string text = value ?? string.Empty;
ParseScheme(text, text.Length, true);
}
}
[DomName("protocol")]
public string Protocol {
get {
return _scheme + ":";
}
set {
Scheme = value;
}
}
[System.Runtime.CompilerServices.Nullable(2)]
public string Query {
[System.Runtime.CompilerServices.NullableContext(2)]
get {
return _query;
}
[System.Runtime.CompilerServices.NullableContext(2)]
set {
if (value == null) {
_query = null;
_params?.Reset();
} else
ParseQuery(value, 0, value.Length, true, false);
}
}
[DomName("search")]
public string Search {
get {
if (!string.IsNullOrEmpty(_query))
return "?" + _query;
return string.Empty;
}
set {
if (string.IsNullOrEmpty(value))
Query = null;
else if (value[0] == '?') {
Query = value.Substring(1);
} else {
Query = value;
}
}
}
[DomName("searchParams")]
public UrlSearchParams SearchParams {
get {
return _params ?? (_params = new UrlSearchParams(this));
}
}
private Url(string scheme, string host, string port)
{
_schemeData = string.Empty;
_path = string.Empty;
_scheme = scheme;
_host = host;
_port = port;
_relative = ProtocolNames.IsRelative(_scheme);
}
[System.Runtime.CompilerServices.NullableContext(0)]
[DomConstructor]
public Url(string url, string baseAddress = null)
{
if (baseAddress != null) {
Url baseUrl = new Url(baseAddress);
_error = ParseUrl(url, baseUrl);
} else
_error = ParseUrl(url, null);
}
[System.Runtime.CompilerServices.NullableContext(0)]
public Url(string address)
{
_error = ParseUrl(address, null);
}
[System.Runtime.CompilerServices.NullableContext(0)]
public Url(Url baseAddress, string relativeAddress)
{
_error = ParseUrl(relativeAddress, baseAddress);
}
public Url(Url address)
{
_fragment = address._fragment;
_query = address._query;
_path = address._path;
_scheme = address._scheme;
_port = address._port;
_host = address._host;
_username = address._username;
_password = address._password;
_relative = address._relative;
_schemeData = address._schemeData;
}
public static Url Create(string address)
{
return new Url(address);
}
public static Url Convert(Uri uri)
{
return new Url(uri.OriginalString);
}
public override int GetHashCode()
{
return (((((((((((((((((_fragment != null) ? StringComparer.Ordinal.GetHashCode(_fragment) : 0) * 397) ^ ((_query != null) ? StringComparer.Ordinal.GetHashCode(_query) : 0)) * 397) ^ ((_path != null) ? StringComparer.Ordinal.GetHashCode(_path) : 0)) * 397) ^ ((_scheme != null) ? StringComparer.OrdinalIgnoreCase.GetHashCode(_scheme) : 0)) * 397) ^ ((_port != null) ? StringComparer.Ordinal.GetHashCode(_port) : 0)) * 397) ^ ((_host != null) ? StringComparer.OrdinalIgnoreCase.GetHashCode(_host) : 0)) * 397) ^ ((_username != null) ? StringComparer.Ordinal.GetHashCode(_username) : 0)) * 397) ^ ((_password != null) ? StringComparer.Ordinal.GetHashCode(_password) : 0)) * 397) ^ ((_schemeData != null) ? StringComparer.Ordinal.GetHashCode(_schemeData) : 0);
}
[System.Runtime.CompilerServices.NullableContext(2)]
public override bool Equals(object obj)
{
if (this != obj) {
Url url = obj as Url;
if (url != null)
return Equals(url);
return false;
}
return true;
}
[System.Runtime.CompilerServices.NullableContext(2)]
public bool Equals(Url other)
{
if (other != null && _fragment.Is(other._fragment) && _query.Is(other._query) && _path.Is(other._path) && _scheme.Isi(other._scheme) && _port.Is(other._port) && _host.Isi(other._host) && _username.Is(other._username) && _password.Is(other._password))
return _schemeData.Is(other._schemeData);
return false;
}
public static implicit operator Uri(Url value)
{
return new Uri(value.Serialize(), (!value.IsRelative) ? UriKind.Absolute : UriKind.Relative);
}
[DomName("toJSON")]
public string ToJson()
{
return Serialize();
}
public override string ToString()
{
return Serialize();
}
private string Serialize()
{
StringBuilder stringBuilder = StringBuilderPool.Obtain();
if (!string.IsNullOrEmpty(_scheme))
stringBuilder.Append(_scheme).Append(':');
if (_relative) {
if (!string.IsNullOrEmpty(_host) || !string.IsNullOrEmpty(_scheme)) {
stringBuilder.Append('/').Append('/');
if (!string.IsNullOrEmpty(_username) || _password != null) {
stringBuilder.Append(_username);
if (_password != null)
stringBuilder.Append(':').Append(_password);
stringBuilder.Append('@');
}
stringBuilder.Append(_host);
if (!string.IsNullOrEmpty(_port))
stringBuilder.Append(':').Append(_port);
stringBuilder.Append('/');
}
stringBuilder.Append(_path);
} else
stringBuilder.Append(_schemeData);
if (_query != null)
stringBuilder.Append('?').Append(_query);
if (_fragment != null)
stringBuilder.Append('#').Append(_fragment);
return stringBuilder.ToPool();
}
private bool ParseUrl(string input, [System.Runtime.CompilerServices.Nullable(2)] Url baseUrl = null)
{
Reset(baseUrl ?? DefaultBase);
string text = NormalizeInput(input);
int length = text.Length;
return !ParseScheme(text, length, false);
}
private void Reset(Url baseUrl)
{
_schemeData = string.Empty;
_scheme = baseUrl._scheme;
_host = baseUrl._host;
_path = baseUrl._path;
_query = baseUrl._query;
_port = baseUrl._port;
_relative = ProtocolNames.IsRelative(_scheme);
}
private bool ParseScheme(string input, int length, bool onlyScheme = false)
{
if (length > 0 && input[0].IsLetter()) {
for (int i = 1; i < length; i++) {
char c = input[i];
if (!c.IsAlphanumericAscii()) {
switch (c) {
case '+':
case '-':
case '.':
break;
case ':':
goto IL_004f;
default:
goto IL_0184;
}
}
continue;
IL_004f:
string scheme = _scheme;
_scheme = input.Substring(0, i).ToLowerInvariant();
if (!onlyScheme) {
_relative = ProtocolNames.IsRelative(_scheme);
if (_scheme.Is(ProtocolNames.File)) {
_host = string.Empty;
_port = string.Empty;
_query = null;
return RelativeState(input, i + 1, length);
}
if (!_relative) {
_host = string.Empty;
_port = string.Empty;
_path = string.Empty;
_query = null;
return ParseSchemeData(input, i + 1, length);
}
if (_scheme.Is(scheme)) {
if (++i < length) {
c = input[i];
if (c == '/' && i + 2 < length && input[i + 1] == '/')
return IgnoreSlashesState(input, i + 2, length);
return RelativeState(input, i, length);
}
return false;
}
if (i + 1 < length && input[++i] == '/' && ++i < length && input[i] == '/')
i++;
return IgnoreSlashesState(input, i, length);
}
return true;
}
}
goto IL_0184;
IL_0184:
if (!onlyScheme)
return RelativeState(input, 0, length);
return false;
}
private bool ParseSchemeData(string input, int index, int length)
{
StringBuilder stringBuilder = StringBuilderPool.Obtain();
while (index < length) {
char c = input[index];
switch (c) {
case '?':
_schemeData = stringBuilder.ToPool();
return ParseQuery(input, index + 1, length, false, false);
case '#':
_schemeData = stringBuilder.ToPool();
return ParseFragment(input, index + 1, length);
case '%':
if (index + 2 < length && input[index + 1].IsHex() && input[index + 2].IsHex()) {
stringBuilder.Append(input[index++]);
stringBuilder.Append(input[index++]);
stringBuilder.Append(input[index]);
break;
}
goto default;
default:
if (c.IsInRange(32, 126))
stringBuilder.Append(c);
break;
}
index++;
}
_schemeData = stringBuilder.ToPool();
return true;
}
private bool RelativeState(string input, int index, int length)
{
_relative = true;
if (index != length) {
switch (input[index]) {
case '?':
return ParseQuery(input, index + 1, length, false, false);
case '#':
return ParseFragment(input, index + 1, length);
case '/':
case '\\':
if (index != length - 1) {
char c2 = input[++index];
if ((c2 == '/' || c2 == '\\') ? true : false) {
if (_scheme.Is(ProtocolNames.File))
return ParseFileHost(input, index + 1, length);
return IgnoreSlashesState(input, index + 1, length);
}
if (_scheme.Is(ProtocolNames.File)) {
_host = string.Empty;
_port = string.Empty;
}
return ParsePath(input, index - 1, length, false);
}
return ParsePath(input, index, length, false);
default: {
bool flag = input[index].IsLetter() && _scheme.Is(ProtocolNames.File) && index + 1 < length;
if (flag) {
char c = input[index + 1];
bool flag2 = (c == '/' || c == ':') ? true : false;
flag = flag2;
}
bool flag3 = flag;
if (flag3) {
bool flag2 = index + 2 == length;
if (!flag2) {
bool flag4;
switch (input[index + 2]) {
case '#':
case '/':
case '?':
case '\\':
flag4 = true;
break;
default:
flag4 = false;
break;
}
flag2 = flag4;
}
flag3 = flag2;
}
if (flag3) {
_host = string.Empty;
_path = string.Empty;
_port = string.Empty;
}
return ParsePath(input, index, length, false);
}
}
}
return true;
}
private bool IgnoreSlashesState(string input, int index, int length)
{
while (index < length) {
char c = input[index];
if ((c != '/' && c != '\\') || 1 == 0)
return ParseAuthority(input, index, length);
index++;
}
return false;
}
private bool ParseAuthority(string input, int index, int length)
{
int index2 = index;
StringBuilder stringBuilder = StringBuilderPool.Obtain();
string text = null;
string password = null;
while (true) {
if (index < length) {
char c = input[index];
switch (c) {
case '@':
if (text == null)
text = stringBuilder.ToString();
else
password = stringBuilder.ToString();
_username = text;
_password = password;
stringBuilder.Append("%40");
index2 = index + 1;
goto IL_0134;
case ':':
if (text != null)
goto default;
text = stringBuilder.ToString();
password = string.Empty;
stringBuilder.Clear();
goto IL_0134;
default:
{
if (c == '%' && index + 2 < length && input[index + 1].IsHex() && input[index + 2].IsHex())
stringBuilder.Append(input[index++]).Append(input[index++]).Append(input[index]);
else {
bool flag;
switch (c) {
case '#':
case '/':
case '?':
case '\\':
flag = true;
break;
default:
flag = false;
break;
}
if (flag)
break;
switch (c) {
default:
if (c.IsNormalPathCharacter())
goto case '#';
goto case ':';
case '#':
case '?':
stringBuilder.Append(c);
break;
case ':':
index += Utf8PercentEncode(stringBuilder, input, index);
break;
}
}
goto IL_0134;
}
IL_0134:
index++;
continue;
}
}
break;
}
stringBuilder.ReturnToPool();
return ParseHostName(input, index2, length, false, false);
}
private bool ParseFileHost(string input, int index, int length)
{
int num = index;
_path = string.Empty;
bool flag;
while (index < length) {
switch (input[index]) {
case '#':
case '/':
case '?':
case '\\':
flag = true;
break;
default:
flag = false;
break;
}
if (flag)
break;
index++;
}
int num2 = index - num;
flag = (num2 == 2 && input[num].IsLetter());
if (flag) {
char c = input[num + 1];
bool flag2 = (c == ':' || c == '|') ? true : false;
flag = flag2;
}
if (flag)
return ParsePath(input, index - 2, length, false);
if (num2 != 0 && !TrySanatizeHost(input, num, num2, out _host))
return false;
return ParsePath(input, index, length, false);
}
private bool ParseHostName(string input, int index, int length, bool onlyHost = false, bool onlyPort = false)
{
bool flag = false;
int num = index;
while (index < length) {
switch (input[index]) {
case ']':
flag = false;
break;
case '[':
flag = true;
break;
case ':':
if (!flag) {
if (!TrySanatizeHost(input, num, index - num, out _host))
return false;
if (!onlyHost)
return ParsePort(input, index + 1, length, onlyPort);
return true;
}
break;
case '#':
case '/':
case '?':
case '\\': {
if (!TrySanatizeHost(input, num, index - num, out _host))
return false;
bool flag2 = string.IsNullOrEmpty(_host);
if (!onlyHost) {
_port = string.Empty;
if (ParsePath(input, index, length, false))
return !flag2;
return false;
}
return !flag2;
}
}
index++;
}
if (!TrySanatizeHost(input, num, index - num, out _host))
return false;
if (!onlyHost) {
_path = string.Empty;
_port = string.Empty;
_query = null;
_fragment = null;
_params?.Reset();
}
return true;
}
private bool ParsePort(string input, int index, int length, bool onlyPort = false)
{
int num = index;
while (index < length) {
char c = input[index];
if (c == '?' || c == '/' || c == '\\' || c == '#')
break;
if (!c.IsDigit())
return false;
index++;
}
_port = SanatizePort(input, num, index - num);
if (PortNumbers.GetDefaultPort(_scheme) == _port)
_port = string.Empty;
if (!onlyPort) {
_path = string.Empty;
return ParsePath(input, index, length, false);
}
return true;
}
private bool ParsePath(string input, int index, int length, bool onlyPath = false)
{
int num = index;
if (index < length && (input[index] == '/' || input[index] == '\\'))
index++;
List<string> list = new List<string>();
if (!onlyPath && !string.IsNullOrEmpty(_path) && index - num == 0) {
string[] array = _path.Split(new char[1] {
'/'
});
if (array.Length > 1) {
list.AddRange(array);
list.RemoveAt(array.Length - 1);
}
}
int count = list.Count;
StringBuilder stringBuilder = StringBuilderPool.Obtain();
while (index <= length) {
char c = (index == length) ? '' : input[index];
bool flag = !onlyPath && (c == '#' || c == '?');
if ((c == '' || c == '/' || c == '\\') | flag) {
string text = stringBuilder.ToString();
bool flag2 = false;
stringBuilder.Clear();
if (text.Isi(CurrentDirectoryAlternative))
text = CurrentDirectory;
else if (text.Isi(UpperDirectoryAlternatives[0]) || text.Isi(UpperDirectoryAlternatives[1]) || text.Isi(UpperDirectoryAlternatives[2])) {
text = UpperDirectory;
}
if (text.Is(UpperDirectory)) {
if (list.Count > 0)
list.RemoveAt(list.Count - 1);
flag2 = true;
} else if (!text.Is(CurrentDirectory)) {
if (_scheme.Is(ProtocolNames.File) && list.Count == count && text.Length == 2 && text[0].IsLetter() && text[1] == '|') {
text = text.Replace('|', ':');
list.Clear();
}
list.Add(text);
} else {
flag2 = true;
}
if (flag2 && c != '/' && c != '\\')
list.Add(string.Empty);
if (flag)
break;
} else if (c == '%' && index + 2 < length && input[index + 1].IsHex() && input[index + 2].IsHex()) {
stringBuilder.Append(input[index++]);
stringBuilder.Append(input[index++]);
stringBuilder.Append(input[index]);
} else if (c.IsNormalPathCharacter()) {
stringBuilder.Append(c);
} else {
index += Utf8PercentEncode(stringBuilder, input, index);
}
index++;
}
stringBuilder.ReturnToPool();
_path = string.Join("/", list);
_query = null;
if (index < length) {
if (input[index] == '?')
return ParseQuery(input, index + 1, length, false, false);
return ParseFragment(input, index + 1, length);
}
return true;
}
internal bool ParseQuery(string input, int index, int length, bool onlyQuery = false, bool fromParams = false)
{
StringBuilder stringBuilder = StringBuilderPool.Obtain();
bool flag = false;
while (index < length) {
char c = input[index];
flag = (!onlyQuery && input[index] == '#');
if (flag)
break;
if (c.IsNormalQueryCharacter())
stringBuilder.Append(c);
else
index += Utf8PercentEncode(stringBuilder, input, index);
index++;
}
_query = stringBuilder.ToPool();
if (!fromParams)
_params?.ChangeTo(_query, true);
if (!flag)
return true;
return ParseFragment(input, index + 1, length);
}
private bool ParseFragment(string input, int index, int length)
{
StringBuilder stringBuilder = StringBuilderPool.Obtain();
while (index < length) {
char c = input[index];
if (c != 0 && c != '')
stringBuilder.Append(c);
index++;
}
_fragment = stringBuilder.ToPool();
return true;
}
private static string NormalizeInput(string input)
{
string text = input.Trim(C0ControlAndSpace);
StringBuilder stringBuilder = StringBuilderPool.Obtain();
string text2 = text;
foreach (char c in text2) {
switch (c) {
default:
stringBuilder.Append(c);
break;
case '\t':
case '\n':
case '\r':
break;
}
}
return stringBuilder.ToPool();
}
private static string Utf8PercentDecode(string source)
{
byte[] bytes = TextEncoding.Utf8.GetBytes(source);
int num = bytes.Length;
int num2 = 0;
int num3 = 0;
while (num2 < bytes.Length) {
char c = (char)bytes[num2];
if (c == '%' && num2 + 2 < bytes.Length && ((char)bytes[num2 + 1]).IsHex() && ((char)bytes[num2 + 2]).IsHex()) {
c = (char)(((char)bytes[num2 + 1]).FromHex() * 16 + ((char)bytes[num2 + 2]).FromHex());
num2 += 2;
num -= 2;
}
bytes[num3] = (byte)c;
num2++;
num3++;
}
return TextEncoding.Utf8.GetString(bytes, 0, num);
}
private static int Utf8PercentEncode(StringBuilder buffer, string source, int index)
{
int num = (!char.IsSurrogatePair(source, index)) ? 1 : 2;
byte[] bytes = TextEncoding.Utf8.GetBytes(source.Substring(index, num));
for (int i = 0; i < bytes.Length; i++) {
buffer.Append('%').Append(bytes[i].ToString("X2"));
}
return num - 1;
}
private static bool TrySanatizeHost(string hostName, int start, int length, out string sanatizedHostName)
{
if (length == 0) {
sanatizedHostName = string.Empty;
return true;
}
if (length > 1 && hostName[start] == '[' && hostName[start + length - 1] == ']') {
sanatizedHostName = hostName.Substring(start, length);
return true;
}
string unicode = Utf8PercentDecode(hostName.Substring(start, length));
string ascii;
try {
ascii = DefaultIdnMapping.GetAscii(unicode);
} catch (ArgumentException) {
sanatizedHostName = hostName.Substring(start, length);
return false;
}
StringBuilder stringBuilder = StringBuilderPool.Obtain();
string text = ascii;
foreach (char c in text) {
switch (c) {
case ' ':
case '\t':
case '\n':
case '\r':
case ' ':
case '#':
case '%':
case '/':
case ':':
case '?':
case '@':
case '[':
case '\\':
case ']':
stringBuilder.ReturnToPool();
sanatizedHostName = hostName.Substring(start, length);
return false;
}
stringBuilder.Append(char.ToLowerInvariant(c));
}
sanatizedHostName = stringBuilder.ToPool();
return true;
}
private unsafe static string SanatizePort(string port, int start, int length)
{
<>c__DisplayClass104_0 <>c__DisplayClass104_ = default(<>c__DisplayClass104_0);
<>c__DisplayClass104_.start = start;
<>c__DisplayClass104_.length = length;
<>c__DisplayClass104_.port = port;
if (<>c__DisplayClass104_.length < 128) {
int length2 = <>c__DisplayClass104_.length;
return <SanatizePort>g__Go|104_0(new Span<char>(stackalloc byte[(int)checked(unchecked((ulong)(uint)length2) * 2)], length2), ref <>c__DisplayClass104_);
}
return <SanatizePort>g__Go|104_0(new char[<>c__DisplayClass104_.length], ref <>c__DisplayClass104_);
}
}
}