summary refs log tree commit diff stats
path: root/lib/pure/uri.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/uri.nim')
-rw-r--r--lib/pure/uri.nim107
1 files changed, 70 insertions, 37 deletions
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index 2c65d071e..b0afb75f9 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2014 Dominik Picheta
+#        (c) Copyright 2015 Dominik Picheta
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -16,17 +16,19 @@ type
   Uri* = object
     scheme*, username*, password*: string 
     hostname*, port*, path*, query*, anchor*: string
+    opaque*: bool
 
 {.deprecated: [TUrl: Url, TUri: Uri].}
 
-proc `$`*(url: TUrl): string {.deprecated.} =
-  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
+{.push warning[deprecated]: off.}
+proc `$`*(url: Url): string {.deprecated.} =
+  ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   return string(url)
 
-proc `/`*(a, b: TUrl): TUrl {.deprecated.} =
+proc `/`*(a, b: Url): Url {.deprecated.} =
   ## Joins two URLs together, separating them with / if needed.
   ##
-  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
+  ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   var urlS = $a
   var bS = $b
   if urlS == "": return b
@@ -36,15 +38,16 @@ proc `/`*(a, b: TUrl): TUrl {.deprecated.} =
     urlS.add(bS.substr(1))
   else:
     urlS.add(bs)
-  result = TUrl(urlS)
+  result = Url(urlS)
 
-proc add*(url: var TUrl, a: TUrl) {.deprecated.} =
+proc add*(url: var Url, a: Url) {.deprecated.} =
   ## Appends url to url.
   ##
-  ## **Deprecated since 0.9.6**: Use ``TUri`` instead.
+  ## **Deprecated since 0.9.6**: Use ``Uri`` instead.
   url = url / a
+{.pop.}
 
-proc parseAuthority(authority: string, result: var TUri) =
+proc parseAuthority(authority: string, result: var Uri) =
   var i = 0
   var inPort = false
   while true:
@@ -65,7 +68,7 @@ proc parseAuthority(authority: string, result: var TUri) =
         result.hostname.add(authority[i])
     i.inc
 
-proc parsePath(uri: string, i: var int, result: var TUri) =
+proc parsePath(uri: string, i: var int, result: var Uri) =
   
   i.inc parseUntil(uri, result.path, {'?', '#'}, i)
 
@@ -82,11 +85,11 @@ proc parsePath(uri: string, i: var int, result: var TUri) =
     i.inc # Skip '#'
     i.inc parseUntil(uri, result.anchor, {}, i)
 
-proc initUri(): TUri =
-  result = TUri(scheme: "", username: "", password: "", hostname: "", port: "",
+proc initUri(): Uri =
+  result = Uri(scheme: "", username: "", password: "", hostname: "", port: "",
                 path: "", query: "", anchor: "")
 
-proc parseUri*(uri: string): TUri =
+proc parseUri*(uri: string): Uri =
   ## Parses a URI.
   result = initUri()
 
@@ -113,8 +116,10 @@ proc parseUri*(uri: string): TUri =
     var authority = ""
     i.inc parseUntil(uri, authority, {'/', '?', '#'}, i)
     if authority == "":
-      raise newException(EInvalidValue, "Expected authority got nothing.")
+      raise newException(ValueError, "Expected authority got nothing.")
     parseAuthority(authority, result)
+  else:
+    result.opaque = true
 
   # Path
   parsePath(uri, i, result)
@@ -150,7 +155,7 @@ proc removeDotSegments(path: string): string =
   result = collection.join("/")
   if endsWithSlash: result.add '/'
 
-proc merge(base, reference: TUri): string =
+proc merge(base, reference: Uri): string =
   # http://tools.ietf.org/html/rfc3986#section-5.2.3
   if base.hostname != "" and base.path == "":
     '/' & reference.path
@@ -161,7 +166,7 @@ proc merge(base, reference: TUri): string =
     else:
       base.path[0 .. lastSegment] & reference.path
 
-proc combine*(base: TUri, reference: TUri): TUri =
+proc combine*(base: Uri, reference: Uri): Uri =
   ## Combines a base URI with a reference URI.
   ##
   ## This uses the algorithm specified in
@@ -179,10 +184,10 @@ proc combine*(base: TUri, reference: TUri): TUri =
   ##   assert foo.path == "/baz"
   ##
   ##   let bar = combine(parseUri("http://example.com/foo/bar"), parseUri("baz"))
-  ##   assert foo.path == "/foo/baz"
+  ##   assert bar.path == "/foo/baz"
   ##
   ##   let bar = combine(parseUri("http://example.com/foo/bar/"), parseUri("baz"))
-  ##   assert foo.path == "/foo/bar/baz"
+  ##   assert bar.path == "/foo/bar/baz"
   
   template setAuthority(dest, src: expr): stmt =
     dest.hostname = src.hostname
@@ -216,13 +221,13 @@ proc combine*(base: TUri, reference: TUri): TUri =
     result.scheme = base.scheme
   result.anchor = reference.anchor
 
-proc combine*(uris: varargs[TUri]): TUri =
+proc combine*(uris: varargs[Uri]): Uri =
   ## Combines multiple URIs together.
   result = uris[0]
   for i in 1 .. <uris.len:
     result = combine(result, uris[i])
 
-proc `/`*(x: TUri, path: string): TUri =
+proc `/`*(x: Uri, path: string): Uri =
   ## Concatenates the path specified to the specified URI's path.
   ##
   ## Contrary to the ``combine`` procedure you do not have to worry about
@@ -236,10 +241,10 @@ proc `/`*(x: TUri, path: string): TUri =
   ##   assert foo.path == "/foo/bar/baz"
   ##
   ##   let bar = parseUri("http://example.com/foo/bar") / parseUri("baz")
-  ##   assert foo.path == "/foo/bar/baz"
+  ##   assert bar.path == "/foo/bar/baz"
   ##
   ##   let bar = parseUri("http://example.com/foo/bar/") / parseUri("baz")
-  ##   assert foo.path == "/foo/bar/baz"
+  ##   assert bar.path == "/foo/bar/baz"
   result = x
   if result.path[result.path.len-1] == '/':
     if path[0] == '/':
@@ -251,12 +256,15 @@ proc `/`*(x: TUri, path: string): TUri =
       result.path.add '/'
     result.path.add(path)
 
-proc `$`*(u: TUri): string =
+proc `$`*(u: Uri): string =
   ## Returns the string representation of the specified URI object.
   result = ""
   if u.scheme.len > 0:
     result.add(u.scheme)
-    result.add("://")
+    if u.opaque:
+      result.add(":")
+    else:
+      result.add("://")
   if u.username.len > 0:
     result.add(u.username)
     if u.password.len > 0:
@@ -268,22 +276,38 @@ proc `$`*(u: TUri): string =
     result.add(":")
     result.add(u.port)
   if u.path.len > 0:
-    if u.path[0] != '/': result.add("/")
     result.add(u.path)
-  result.add(u.query)
-  result.add(u.anchor)
+  if u.query.len > 0:
+    result.add("?")
+    result.add(u.query)
+  if u.anchor.len > 0:
+    result.add("#")
+    result.add(u.anchor)
 
 when isMainModule:
   block:
-    let test = parseUri("http://localhost:8080/test")
+    let str = "http://localhost"
+    let test = parseUri(str)
+    doAssert test.path == ""
+
+  block:
+    let str = "http://localhost/"
+    let test = parseUri(str)
+    doAssert test.path == "/"
+
+  block:
+    let str = "http://localhost:8080/test"
+    let test = parseUri(str)
     doAssert test.scheme == "http"
     doAssert test.port == "8080"
     doAssert test.path == "/test"
     doAssert test.hostname == "localhost"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("foo://username:password@example.com:8042/over/there" &
-                        "/index.dtb?type=animal&name=narwhal#nose")
+    let str = "foo://username:password@example.com:8042/over/there" &
+              "/index.dtb?type=animal&name=narwhal#nose"
+    let test = parseUri(str)
     doAssert test.scheme == "foo"
     doAssert test.username == "username"
     doAssert test.password == "password"
@@ -292,34 +316,45 @@ when isMainModule:
     doAssert test.path == "/over/there/index.dtb"
     doAssert test.query == "type=animal&name=narwhal"
     doAssert test.anchor == "nose"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("urn:example:animal:ferret:nose")
+    let str = "urn:example:animal:ferret:nose"
+    let test = parseUri(str)
     doAssert test.scheme == "urn"
     doAssert test.path == "example:animal:ferret:nose"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("mailto:username@example.com?subject=Topic")
+    let str = "mailto:username@example.com?subject=Topic"
+    let test = parseUri(str)
     doAssert test.scheme == "mailto"
     doAssert test.username == "username"
     doAssert test.hostname == "example.com"
     doAssert test.query == "subject=Topic"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar")
+    let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
+    let test = parseUri(str)
     doAssert test.scheme == "magnet"
     doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("/test/foo/bar?q=2#asdf")
+    let str = "/test/foo/bar?q=2#asdf"
+    let test = parseUri(str)
     doAssert test.scheme == ""
     doAssert test.path == "/test/foo/bar"
     doAssert test.query == "q=2"
     doAssert test.anchor == "asdf"
+    doAssert($test == str)
 
   block:
-    let test = parseUri("test/no/slash")
+    let str = "test/no/slash"
+    let test = parseUri(str)
     doAssert test.path == "test/no/slash"
+    doAssert($test == str)
 
   # Remove dot segments tests
   block:
@@ -371,5 +406,3 @@ when isMainModule:
   block:
     let test = parseUri("http://example.com/foo/") / "/bar/asd"
     doAssert test.path == "/foo/bar/asd"
-
-