@@ -134,6 +134,7 @@ pub const ParseError = error{ UnexpectedCharacter, InvalidFormat, InvalidPort };
134134/// original `text`. Each component that is provided, will be non-`null`.
135135pub fn parseWithoutScheme (text : []const u8 ) ParseError ! Uri {
136136 var reader = SliceReader { .slice = text };
137+
137138 var uri = Uri {
138139 .scheme = "" ,
139140 .user = null ,
@@ -145,13 +146,14 @@ pub fn parseWithoutScheme(text: []const u8) ParseError!Uri {
145146 .fragment = null ,
146147 };
147148
148- if (reader .peekPrefix ("//" )) { // authority part
149+ if (reader .peekPrefix ("//" )) a : { // authority part
149150 std .debug .assert (reader .get ().? == '/' );
150151 std .debug .assert (reader .get ().? == '/' );
151152
152- const authority = reader .readUntil (isAuthoritySeparator );
153- if (authority .len == 0 )
154- return error .InvalidFormat ;
153+ var authority = reader .readUntil (isAuthoritySeparator );
154+ if (authority .len == 0 ) {
155+ if (reader .peekPrefix ("/" )) break :a else return error .InvalidFormat ;
156+ }
155157
156158 var start_of_host : usize = 0 ;
157159 if (std .mem .indexOf (u8 , authority , "@" )) | index | {
@@ -223,7 +225,6 @@ pub fn format(
223225 try writer .writeAll (":" );
224226 if (uri .host ) | host | {
225227 try writer .writeAll ("//" );
226-
227228 if (uri .user ) | user | {
228229 try writer .writeAll (user );
229230 if (uri .password ) | password | {
@@ -473,6 +474,23 @@ test "should fail gracefully" {
473474 try std .testing .expectEqual (@as (ParseError ! Uri , error .InvalidFormat ), parse ("foobar://" ));
474475}
475476
477+ test "file" {
478+ const parsed = try parse ("file:///" );
479+ try std .testing .expectEqualSlices (u8 , "file" , parsed .scheme );
480+ try std .testing .expectEqual (@as (? []const u8 , null ), parsed .host );
481+ try std .testing .expectEqualSlices (u8 , "/" , parsed .path );
482+
483+ const parsed2 = try parse ("file:///an/absolute/path/to/something" );
484+ try std .testing .expectEqualSlices (u8 , "file" , parsed2 .scheme );
485+ try std .testing .expectEqual (@as (? []const u8 , null ), parsed2 .host );
486+ try std .testing .expectEqualSlices (u8 , "/an/absolute/path/to/something" , parsed2 .path );
487+
488+ const parsed3 = try parse ("file://localhost/an/absolute/path/to/another/thing/" );
489+ try std .testing .expectEqualSlices (u8 , "file" , parsed3 .scheme );
490+ try std .testing .expectEqualSlices (u8 , "localhost" , parsed3 .host .? );
491+ try std .testing .expectEqualSlices (u8 , "/an/absolute/path/to/another/thing/" , parsed3 .path );
492+ }
493+
476494test "scheme" {
477495 try std .testing .expectEqualSlices (u8 , "http" , (try parse ("http:_" )).scheme );
478496 try std .testing .expectEqualSlices (u8 , "scheme-mee" , (try parse ("scheme-mee:_" )).scheme );
@@ -682,3 +700,20 @@ test "URI query escaping" {
682700 defer std .testing .allocator .free (formatted_uri );
683701 try std .testing .expectEqualStrings ("/?response-content-type=application%2Foctet-stream" , formatted_uri );
684702}
703+
704+ test "format" {
705+ const uri = Uri {
706+ .scheme = "file" ,
707+ .user = null ,
708+ .password = null ,
709+ .host = null ,
710+ .port = null ,
711+ .path = "/foo/bar/baz" ,
712+ .query = null ,
713+ .fragment = null ,
714+ };
715+ var buf = std .ArrayList (u8 ).init (std .testing .allocator );
716+ defer buf .deinit ();
717+ try uri .format ("+/" , .{}, buf .writer ());
718+ try std .testing .expectEqualSlices (u8 , "file:/foo/bar/baz" , buf .items );
719+ }
0 commit comments