@@ -134,6 +134,7 @@ pub const ParseError = error{ UnexpectedCharacter, InvalidFormat, InvalidPort };
134
134
/// original `text`. Each component that is provided, will be non-`null`.
135
135
pub fn parseWithoutScheme (text : []const u8 ) ParseError ! Uri {
136
136
var reader = SliceReader { .slice = text };
137
+
137
138
var uri = Uri {
138
139
.scheme = "" ,
139
140
.user = null ,
@@ -145,13 +146,14 @@ pub fn parseWithoutScheme(text: []const u8) ParseError!Uri {
145
146
.fragment = null ,
146
147
};
147
148
148
- if (reader .peekPrefix ("//" )) { // authority part
149
+ if (reader .peekPrefix ("//" )) a : { // authority part
149
150
std .debug .assert (reader .get ().? == '/' );
150
151
std .debug .assert (reader .get ().? == '/' );
151
152
152
153
const authority = reader .readUntil (isAuthoritySeparator );
153
- if (authority .len == 0 )
154
- return error .InvalidFormat ;
154
+ if (authority .len == 0 ) {
155
+ if (reader .peekPrefix ("/" )) break :a else return error .InvalidFormat ;
156
+ }
155
157
156
158
var start_of_host : usize = 0 ;
157
159
if (std .mem .indexOf (u8 , authority , "@" )) | index | {
@@ -224,7 +226,6 @@ pub fn format(
224
226
try writer .writeAll (":" );
225
227
if (uri .host ) | host | {
226
228
try writer .writeAll ("//" );
227
-
228
229
if (uri .user ) | user | {
229
230
try writer .writeAll (user );
230
231
if (uri .password ) | password | {
@@ -486,6 +487,23 @@ test "should fail gracefully" {
486
487
try std .testing .expectEqual (@as (ParseError ! Uri , error .InvalidFormat ), parse ("foobar://" ));
487
488
}
488
489
490
+ test "file" {
491
+ const parsed = try parse ("file:///" );
492
+ try std .testing .expectEqualSlices (u8 , "file" , parsed .scheme );
493
+ try std .testing .expectEqual (@as (? []const u8 , null ), parsed .host );
494
+ try std .testing .expectEqualSlices (u8 , "/" , parsed .path );
495
+
496
+ const parsed2 = try parse ("file:///an/absolute/path/to/something" );
497
+ try std .testing .expectEqualSlices (u8 , "file" , parsed2 .scheme );
498
+ try std .testing .expectEqual (@as (? []const u8 , null ), parsed2 .host );
499
+ try std .testing .expectEqualSlices (u8 , "/an/absolute/path/to/something" , parsed2 .path );
500
+
501
+ const parsed3 = try parse ("file://localhost/an/absolute/path/to/another/thing/" );
502
+ try std .testing .expectEqualSlices (u8 , "file" , parsed3 .scheme );
503
+ try std .testing .expectEqualSlices (u8 , "localhost" , parsed3 .host .? );
504
+ try std .testing .expectEqualSlices (u8 , "/an/absolute/path/to/another/thing/" , parsed3 .path );
505
+ }
506
+
489
507
test "scheme" {
490
508
try std .testing .expectEqualSlices (u8 , "http" , (try parse ("http:_" )).scheme );
491
509
try std .testing .expectEqualSlices (u8 , "scheme-mee" , (try parse ("scheme-mee:_" )).scheme );
@@ -695,3 +713,20 @@ test "URI query escaping" {
695
713
defer std .testing .allocator .free (formatted_uri );
696
714
try std .testing .expectEqualStrings ("/?response-content-type=application%2Foctet-stream" , formatted_uri );
697
715
}
716
+
717
+ test "format" {
718
+ const uri = Uri {
719
+ .scheme = "file" ,
720
+ .user = null ,
721
+ .password = null ,
722
+ .host = null ,
723
+ .port = null ,
724
+ .path = "/foo/bar/baz" ,
725
+ .query = null ,
726
+ .fragment = null ,
727
+ };
728
+ var buf = std .ArrayList (u8 ).init (std .testing .allocator );
729
+ defer buf .deinit ();
730
+ try uri .format ("+/" , .{}, buf .writer ());
731
+ try std .testing .expectEqualSlices (u8 , "file:/foo/bar/baz" , buf .items );
732
+ }
0 commit comments