Skip to content

Commit 9e9eb9b

Browse files
authored
Simplify InitializeUri and remove some unreachable branches (#122001)
1 parent 2e0cb6b commit 9e9eb9b

File tree

3 files changed

+118
-167
lines changed

3 files changed

+118
-167
lines changed

src/libraries/System.Private.Uri/src/System/Uri.cs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -700,41 +700,32 @@ private static void GetCombinedString(Uri baseUri, string relativeStr,
700700
}
701701
}
702702

703-
private static UriFormatException? GetException(ParsingError err)
703+
private static UriFormatException GetException(ParsingError err)
704704
{
705-
switch (err)
705+
Debug.Assert(err != ParsingError.None);
706+
707+
string message = err switch
706708
{
707-
case ParsingError.None:
708-
return null;
709709
// Could be OK for Relative Uri
710-
case ParsingError.BadFormat:
711-
return new UriFormatException(SR.net_uri_BadFormat);
712-
case ParsingError.BadScheme:
713-
return new UriFormatException(SR.net_uri_BadScheme);
714-
case ParsingError.BadAuthority:
715-
return new UriFormatException(SR.net_uri_BadAuthority);
716-
case ParsingError.EmptyUriString:
717-
return new UriFormatException(SR.net_uri_EmptyUri);
710+
ParsingError.BadFormat => SR.net_uri_BadFormat,
711+
ParsingError.BadScheme => SR.net_uri_BadScheme,
712+
ParsingError.BadAuthority => SR.net_uri_BadAuthority,
713+
ParsingError.EmptyUriString => SR.net_uri_EmptyUri,
714+
718715
// Fatal
719-
case ParsingError.SchemeLimit:
720-
return new UriFormatException(SR.net_uri_SchemeLimit);
721-
case ParsingError.MustRootedPath:
722-
return new UriFormatException(SR.net_uri_MustRootedPath);
716+
ParsingError.SchemeLimit => SR.net_uri_SchemeLimit,
717+
ParsingError.MustRootedPath => SR.net_uri_MustRootedPath,
718+
723719
// Derived class controllable
724-
case ParsingError.BadHostName:
725-
return new UriFormatException(SR.net_uri_BadHostName);
726-
case ParsingError.NonEmptyHost: //unix-only
727-
return new UriFormatException(SR.net_uri_BadFormat);
728-
case ParsingError.BadPort:
729-
return new UriFormatException(SR.net_uri_BadPort);
730-
case ParsingError.BadAuthorityTerminator:
731-
return new UriFormatException(SR.net_uri_BadAuthorityTerminator);
732-
case ParsingError.CannotCreateRelative:
733-
return new UriFormatException(SR.net_uri_CannotCreateRelative);
734-
default:
735-
break;
736-
}
737-
return new UriFormatException(SR.net_uri_BadFormat);
720+
ParsingError.BadHostName => SR.net_uri_BadHostName,
721+
ParsingError.BadPort => SR.net_uri_BadPort,
722+
ParsingError.BadAuthorityTerminator => SR.net_uri_BadAuthorityTerminator,
723+
ParsingError.CannotCreateRelative => SR.net_uri_CannotCreateRelative,
724+
725+
_ => throw new UnreachableException()
726+
};
727+
728+
return new UriFormatException(message);
738729
}
739730

740731
public string AbsolutePath

src/libraries/System.Private.Uri/src/System/UriEnumTypes.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ internal enum ParsingError
7373

7474
// derived class controlled
7575
BadHostName,
76-
NonEmptyHost, // unix only
7776
BadPort,
7877
BadAuthorityTerminator,
7978

src/libraries/System.Private.Uri/src/System/UriExt.cs

Lines changed: 97 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind, in UriCre
2121
{
2222
DebugAssertInCtor();
2323

24-
if ((int)uriKind < (int)UriKind.RelativeOrAbsolute || (int)uriKind > (int)UriKind.Relative)
24+
if (uriKind is < UriKind.RelativeOrAbsolute or > UriKind.Relative)
2525
{
2626
throw new ArgumentException(SR.Format(SR.net_uri_InvalidUriKind, uriKind));
2727
}
@@ -38,176 +38,137 @@ private void CreateThis(string? uri, bool dontEscape, UriKind uriKind, in UriCre
3838

3939
ParsingError err = ParseScheme(_string, ref _flags, ref _syntax!);
4040

41-
InitializeUri(err, uriKind, out UriFormatException? e);
41+
UriFormatException? e = InitializeUri(err, uriKind);
4242
if (e != null)
4343
throw e;
4444
}
4545

46-
private void InitializeUri(ParsingError err, UriKind uriKind, out UriFormatException? e)
46+
private UriFormatException? InitializeUri(ParsingError err, UriKind uriKind)
4747
{
4848
DebugAssertInCtor();
49+
Debug.Assert((err is ParsingError.None) == (_syntax is not null));
50+
51+
bool hasUnicode = false;
4952

50-
if (err == ParsingError.None)
53+
if (IriParsing && CheckForUnicodeOrEscapedUnreserved(_string))
54+
{
55+
_flags |= Flags.HasUnicode;
56+
hasUnicode = true;
57+
_originalUnicodeString = _string; // original string location changed
58+
}
59+
60+
if (err != ParsingError.None)
5161
{
52-
if (IsImplicitFile)
62+
// If we encountered any parsing errors that indicate this may be a relative Uri,
63+
// and we'll allow relative Uri's, then create one.
64+
if (uriKind != UriKind.Absolute && err <= ParsingError.LastErrorOkayForRelativeUris)
5365
{
54-
// V1 compat
55-
// A relative Uri wins over implicit UNC path unless the UNC path is of the form "\\something" and
56-
// uriKind != Absolute
57-
// A relative Uri wins over implicit Unix path unless uriKind == Absolute
58-
if (NotAny(Flags.DosPath) &&
59-
uriKind != UriKind.Absolute &&
60-
((uriKind == UriKind.Relative || (_string.Length >= 2 && (_string[0] != '\\' || _string[1] != '\\')))
61-
|| (!OperatingSystem.IsWindows() && InFact(Flags.UnixPath))))
62-
{
63-
_syntax = null!; //make it be relative Uri
64-
_flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri
65-
e = null;
66-
return;
67-
// Otherwise an absolute file Uri wins when it's of the form "\\something"
68-
}
69-
//
70-
// V1 compat issue
71-
// We should support relative Uris of the form c:\bla or c:/bla
72-
//
73-
else if (uriKind == UriKind.Relative && InFact(Flags.DosPath))
66+
_flags &= Flags.UserEscaped | Flags.HasUnicode; // the only flags that makes sense for a relative uri
67+
if (hasUnicode)
7468
{
75-
_syntax = null!; //make it be relative Uri
76-
_flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri
77-
e = null;
78-
return;
79-
// Otherwise an absolute file Uri wins when it's of the form "c:\something"
69+
// Iri'ze and then normalize relative uris
70+
_string = EscapeUnescapeIri(_originalUnicodeString, 0, _originalUnicodeString.Length, isQuery: false);
8071
}
72+
return null;
8173
}
82-
}
83-
else if (err > ParsingError.LastErrorOkayForRelativeUris)
84-
{
85-
//This is a fatal error based solely on scheme name parsing
74+
75+
// This is a fatal error based solely on scheme name parsing
8676
_string = null!; // make it be invalid Uri
87-
e = GetException(err);
88-
return;
77+
return GetException(err);
8978
}
9079

91-
bool hasUnicode = false;
80+
Debug.Assert(_syntax is not null);
9281

93-
if (IriParsing && CheckForUnicodeOrEscapedUnreserved(_string))
82+
if (IsImplicitFile)
9483
{
95-
_flags |= Flags.HasUnicode;
96-
hasUnicode = true;
97-
// switch internal strings
98-
_originalUnicodeString = _string; // original string location changed
84+
if (uriKind == UriKind.Relative)
85+
{
86+
_syntax = null!; // make it be relative Uri
87+
_flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri
88+
return null;
89+
}
90+
91+
// V1 compat
92+
// A relative Uri wins over implicit UNC path unless the UNC path is of the form "\\something" and
93+
// uriKind != Absolute
94+
// A relative Uri wins over implicit Unix path unless uriKind == Absolute
95+
if (NotAny(Flags.DosPath) && uriKind == UriKind.RelativeOrAbsolute &&
96+
((_string.Length >= 2 && (_string[0] != '\\' || _string[1] != '\\'))
97+
|| (!OperatingSystem.IsWindows() && InFact(Flags.UnixPath))))
98+
{
99+
_syntax = null!; //make it be relative Uri
100+
_flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri
101+
return null;
102+
// Otherwise an absolute file Uri wins when it's of the form "\\something"
103+
}
99104
}
100105

101-
if (_syntax != null)
106+
if (_syntax.IsSimple)
102107
{
103-
if (_syntax.IsSimple)
108+
if ((err = PrivateParseMinimal()) != ParsingError.None)
104109
{
105-
if ((err = PrivateParseMinimal()) != ParsingError.None)
106-
{
107-
if (uriKind != UriKind.Absolute && err <= ParsingError.LastErrorOkayForRelativeUris)
108-
{
109-
// RFC 3986 Section 5.4.2 - http:(relativeUri) may be considered a valid relative Uri.
110-
_syntax = null!; // convert to relative uri
111-
e = null;
112-
_flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri
113-
return;
114-
}
115-
else
116-
e = GetException(err);
117-
}
118-
else if (uriKind == UriKind.Relative)
110+
if (uriKind != UriKind.Absolute && err <= ParsingError.LastErrorOkayForRelativeUris)
119111
{
120-
// Here we know that we can create an absolute Uri, but the user has requested only a relative one
121-
e = GetException(ParsingError.CannotCreateRelative);
112+
// RFC 3986 Section 5.4.2 - http:(relativeUri) may be considered a valid relative Uri.
113+
_syntax = null!; // convert to relative uri
114+
_flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri
115+
return null;
122116
}
123-
else
124-
e = null;
125-
// will return from here
126117

127-
if (e is null && hasUnicode)
128-
{
129-
// In this scenario we need to parse the whole string
130-
try
131-
{
132-
EnsureParseRemaining();
133-
}
134-
catch (UriFormatException ex)
135-
{
136-
e = ex;
137-
}
138-
}
118+
return GetException(err);
139119
}
140-
else
120+
121+
if (uriKind == UriKind.Relative)
141122
{
142-
// offer custom parser to create a parsing context
143-
_syntax = _syntax.InternalOnNewUri();
123+
// Here we know that we can create an absolute Uri, but the user has requested only a relative one
124+
return GetException(ParsingError.CannotCreateRelative);
125+
}
126+
}
127+
else
128+
{
129+
// offer custom parser to create a parsing context
130+
_syntax = _syntax.InternalOnNewUri();
144131

145-
// in case they won't call us
146-
_flags |= Flags.UserDrivenParsing;
132+
// in case they won't call us
133+
_flags |= Flags.UserDrivenParsing;
147134

148-
// Ask a registered type to validate this uri
149-
_syntax.InternalValidate(this, out e);
135+
// Ask a registered type to validate this uri
136+
_syntax.InternalValidate(this, out UriFormatException? e);
150137

151-
if (e != null)
152-
{
153-
// Can we still take it as a relative Uri?
154-
if (uriKind != UriKind.Absolute && err != ParsingError.None
155-
&& err <= ParsingError.LastErrorOkayForRelativeUris)
156-
{
157-
_syntax = null!; // convert it to relative
158-
e = null;
159-
_flags &= Flags.UserEscaped; // the only flag that makes sense for a relative uri
160-
}
161-
}
162-
else // e == null
163-
{
164-
if (err != ParsingError.None || InFact(Flags.ErrorOrParsingRecursion))
165-
{
166-
// User parser took over on an invalid Uri
167-
// we use = here to clear all parsing flags for a uri that we think is invalid.
168-
_flags = Flags.UserDrivenParsing | (_flags & Flags.UserEscaped);
169-
}
170-
else if (uriKind == UriKind.Relative)
171-
{
172-
// Here we know that custom parser can create an absolute Uri, but the user has requested only a
173-
// relative one
174-
e = GetException(ParsingError.CannotCreateRelative);
175-
}
138+
if (e is not null)
139+
{
140+
return e;
141+
}
176142

177-
if (e is null && hasUnicode)
178-
{
179-
// In this scenario we need to parse the whole string
180-
try
181-
{
182-
EnsureParseRemaining();
183-
}
184-
catch (UriFormatException ex)
185-
{
186-
e = ex;
187-
}
188-
}
189-
}
190-
// will return from here
143+
if (InFact(Flags.ErrorOrParsingRecursion))
144+
{
145+
// User parser took over on an invalid Uri
146+
// we use = here to clear all parsing flags for a uri that we think is invalid.
147+
_flags = Flags.UserDrivenParsing | (_flags & Flags.UserEscaped);
191148
}
192-
}
193-
// If we encountered any parsing errors that indicate this may be a relative Uri,
194-
// and we'll allow relative Uri's, then create one.
195-
else if (err != ParsingError.None && uriKind != UriKind.Absolute
196-
&& err <= ParsingError.LastErrorOkayForRelativeUris)
197-
{
198-
e = null;
199-
_flags &= (Flags.UserEscaped | Flags.HasUnicode); // the only flags that makes sense for a relative uri
200-
if (hasUnicode)
149+
else if (uriKind == UriKind.Relative)
201150
{
202-
// Iri'ze and then normalize relative uris
203-
_string = EscapeUnescapeIri(_originalUnicodeString, 0, _originalUnicodeString.Length, isQuery: false);
151+
// Here we know that custom parser can create an absolute Uri, but the user has requested only a
152+
// relative one
153+
return GetException(ParsingError.CannotCreateRelative);
204154
}
205155
}
206-
else
156+
157+
if (hasUnicode)
207158
{
208-
_string = null!; // make it be invalid Uri
209-
e = GetException(err);
159+
// In this scenario we need to parse the whole string
160+
try
161+
{
162+
EnsureParseRemaining();
163+
}
164+
catch (UriFormatException ex)
165+
{
166+
return ex;
167+
}
210168
}
169+
170+
// We have a valid absolute Uri.
171+
return null;
211172
}
212173

213174
/// <summary>SearchValues for all ASCII characters other than %</summary>
@@ -742,7 +703,7 @@ private Uri(Flags flags, UriParser? uriParser, string uri)
742703
// Validate instance using ether built in or a user Parser
743704
try
744705
{
745-
result.InitializeUri(err, uriKind, out e);
706+
e = result.InitializeUri(err, uriKind);
746707

747708
if (e == null)
748709
{

0 commit comments

Comments
 (0)