Skip to content

Commit f757787

Browse files
committed
Attempt to fix the encoder for Windows
1 parent 8d8fea0 commit f757787

File tree

1 file changed

+16
-5
lines changed

1 file changed

+16
-5
lines changed

src/DotNext/IO/FileUri.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
using System.Diagnostics;
33
using System.Runtime.CompilerServices;
44
using System.Text.Encodings.Web;
5-
using DotNext.Buffers;
65

76
namespace DotNext.IO;
87

8+
using Buffers;
9+
910
/// <summary>
1011
/// Represents operations to work with <c>file://</c> scheme.
1112
/// </summary>
@@ -18,6 +19,10 @@ public static class FileUri
1819
// \\.\folder => file://./folder
1920
private const string FileScheme = "file://";
2021
private const string UncPrefix = @"\\";
22+
private const char DriveSeparatorChar = ':';
23+
24+
private static readonly SearchValues<char> Delimiters =
25+
SearchValues.Create(OperatingSystem.IsWindows() ? [Path.DirectorySeparatorChar, DriveSeparatorChar] : [Path.DirectorySeparatorChar]);
2126

2227
/// <summary>
2328
/// Encodes file name as URI.
@@ -79,6 +84,7 @@ private static void ThrowIfNotFullyQualified(ReadOnlySpan<char> fileName)
7984
private static bool TryEncodeCore(ReadOnlySpan<char> fileName, UrlEncoder encoder, Span<char> output, out int charsWritten)
8085
{
8186
const char slash = '/';
87+
const char escapedDriveSeparatorChar = '|';
8288
var result = false;
8389
var writer = new SpanWriter<char>(output);
8490
writer.Write(FileScheme);
@@ -92,31 +98,36 @@ private static bool TryEncodeCore(ReadOnlySpan<char> fileName, UrlEncoder encode
9298
}
9399
else
94100
{
95-
writer.Add(Path.DirectorySeparatorChar);
101+
writer.Add(slash);
96102
}
97103

98104
while (!fileName.IsEmpty)
99105
{
100-
var index = fileName.IndexOf(Path.DirectorySeparatorChar);
106+
var index = fileName.IndexOfAny(Delimiters);
107+
char replacement;
101108
ReadOnlySpan<char> component;
102109
if (index >= 0)
103110
{
104111
component = fileName.Slice(0, index);
105112
fileName = fileName.Slice(index + 1);
113+
replacement = OperatingSystem.IsWindows() && fileName[index] is DriveSeparatorChar
114+
? escapedDriveSeparatorChar
115+
: slash;
106116
}
107117
else
108118
{
109119
component = fileName;
110120
fileName = default;
121+
replacement = '\0';
111122
}
112123

113124
result = encoder.Encode(component, writer.RemainingSpan, out _, out charsWritten) is OperationStatus.Done;
114125
if (!result)
115126
break;
116127

117128
writer.Advance(charsWritten);
118-
if (index >= 0)
119-
writer.Add(Path.DirectorySeparatorChar);
129+
if (replacement is not '\0')
130+
writer.Add(replacement);
120131
}
121132

122133
charsWritten = writer.WrittenCount;

0 commit comments

Comments
 (0)