Skip to content

Commit

Permalink
Provide uri record, remove accessor functions
Browse files Browse the repository at this point in the history
  • Loading branch information
alex-snezhko committed Jan 29, 2024
1 parent 3e832a1 commit 8462b35
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 346 deletions.
181 changes: 102 additions & 79 deletions compiler/test/stdlib/uri.test.gr
Expand Up @@ -3,146 +3,169 @@ module UriTest
include "uri"
include "result"

record Uri {
scheme: Option<String>,
userinfo: Option<String>,
host: Option<String>,
port: Option<Number>,
path: String,
query: Option<String>,
fragment: Option<String>,
string: String,
record ExpectedUri {
expectedScheme: Option<String>,
expectedUserinfo: Option<String>,
expectedHost: Option<String>,
expectedPort: Option<Number>,
expectedPath: String,
expectedQuery: Option<String>,
expectedFragment: Option<String>,
expectedString: String,
}

let default = {
scheme: None,
userinfo: None,
host: None,
port: None,
path: "",
query: None,
fragment: None,
string: "",
expectedScheme: None,
expectedUserinfo: None,
expectedHost: None,
expectedPort: None,
expectedPath: "",
expectedQuery: None,
expectedFragment: None,
expectedString: "",
}

let testValid = (uriString, expected) => {
let uri = Result.unwrap(Uri.parse(uriString))
assert Uri.scheme(uri) == expected.scheme
assert Uri.userinfo(uri) == expected.userinfo
assert Uri.host(uri) == expected.host
assert Uri.port(uri) == expected.port
assert Uri.path(uri) == expected.path
assert Uri.query(uri) == expected.query
assert Uri.fragment(uri) == expected.fragment
assert uri.scheme == expected.expectedScheme
assert uri.userinfo == expected.expectedUserinfo
assert uri.host == expected.expectedHost
assert uri.port == expected.expectedPort
assert uri.path == expected.expectedPath
assert uri.query == expected.expectedQuery
assert uri.fragment == expected.expectedFragment
assert Uri.toString(uri) ==
(if (expected.string == "") uriString else expected.string)
(if (expected.expectedString == "") uriString else expected.expectedString)
}

testValid(
"https://grain-lang.org",
{ ...default, scheme: Some("https"), host: Some("grain-lang.org") }
{
...default,
expectedScheme: Some("https"),
expectedHost: Some("grain-lang.org"),
}
)
testValid(
"http://user:password@www.domain.com:80/path/inner?q1=v1&q2=v2#frag",
{
...default,
scheme: Some("http"),
userinfo: Some("user:password"),
host: Some("www.domain.com"),
port: Some(80),
path: "/path/inner",
query: Some("q1=v1&q2=v2"),
fragment: Some("frag"),
expectedScheme: Some("http"),
expectedUserinfo: Some("user:password"),
expectedHost: Some("www.domain.com"),
expectedPort: Some(80),
expectedPath: "/path/inner",
expectedQuery: Some("q1=v1&q2=v2"),
expectedFragment: Some("frag"),
}
)
testValid(
"http://www.domain.com:80/path?q1=v1/?q2=v2#frag/?",
{
...default,
scheme: Some("http"),
host: Some("www.domain.com"),
port: Some(80),
path: "/path",
query: Some("q1=v1/?q2=v2"),
fragment: Some("frag/?"),
expectedScheme: Some("http"),
expectedHost: Some("www.domain.com"),
expectedPort: Some(80),
expectedPath: "/path",
expectedQuery: Some("q1=v1/?q2=v2"),
expectedFragment: Some("frag/?"),
}
)
testValid(
"a12+3-4.5://1a-._~%1f%Fa!$&'()*+,;=:@0.99.100.255://?1%1f@:/?#/?a",
{
...default,
scheme: Some("a12+3-4.5"),
userinfo: Some(
expectedScheme: Some("a12+3-4.5"),
expectedUserinfo: Some(
"1a-._~%1f%Fa!$&'()*+,;=:"
), // Do not turn %1f into %1F in userinfo
host: Some("0.99.100.255"),
path: "//",
query: Some("1%1F@:/?"),
fragment: Some("/?a"),
string: "a12+3-4.5://1a-._~%1f%Fa!$&'()*+,;=:@0.99.100.255//?1%1F@:/?#/?a",
expectedHost: Some("0.99.100.255"),
expectedPath: "//",
expectedQuery: Some("1%1F@:/?"),
expectedFragment: Some("/?a"),
expectedString: "a12+3-4.5://1a-._~%1f%Fa!$&'()*+,;=:@0.99.100.255//?1%1F@:/?#/?a",
}
)
testValid(
"mailto:me@email.com",
{ ...default, scheme: Some("mailto"), path: "me@email.com" }
{ ...default, expectedScheme: Some("mailto"), expectedPath: "me@email.com" }
)
testValid(
"urn:hello:world",
{ ...default, scheme: Some("urn"), path: "hello:world" }
{ ...default, expectedScheme: Some("urn"), expectedPath: "hello:world" }
)
testValid(
"tel:+1-888-888-8888",
{ ...default, scheme: Some("tel"), path: "+1-888-888-8888" }
{ ...default, expectedScheme: Some("tel"), expectedPath: "+1-888-888-8888" }
)
testValid(
"scheme:/",
{ ...default, expectedScheme: Some("scheme"), expectedPath: "/" }
)
testValid(
"scheme://",
{ ...default, expectedScheme: Some("scheme"), expectedHost: Some("") }
)
testValid("scheme:/", { ...default, scheme: Some("scheme"), path: "/" })
testValid("scheme://", { ...default, scheme: Some("scheme"), host: Some("") })
testValid(
"scheme:///",
{ ...default, scheme: Some("scheme"), host: Some(""), path: "/" }
{
...default,
expectedScheme: Some("scheme"),
expectedHost: Some(""),
expectedPath: "/",
}
)
testValid(
"ScHeMe://HoSt%2a.COM/Path",
{
...default,
scheme: Some("scheme"),
host: Some("host%2A.com"),
path: "/Path",
string: "scheme://host%2A.com/Path",
expectedScheme: Some("scheme"),
expectedHost: Some("host%2A.com"),
expectedPath: "/Path",
expectedString: "scheme://host%2A.com/Path",
}
)
testValid(
"scheme://%41:%61@%48%65%6c%6C%6f/%25%7e%68%69",
{
...default,
scheme: Some("scheme"),
userinfo: Some("%41:%61"),
host: Some("hello"),
path: "/%25~hi",
string: "scheme://%41:%61@hello/%25~hi",
expectedScheme: Some("scheme"),
expectedUserinfo: Some("%41:%61"),
expectedHost: Some("hello"),
expectedPath: "/%25~hi",
expectedString: "scheme://%41:%61@hello/%25~hi",
}
)
testValid("scheme:", { ...default, scheme: Some("scheme") })
testValid("scheme:", { ...default, expectedScheme: Some("scheme") })
testValid(
"http://:80",
{ ...default, scheme: Some("http"), host: Some(""), port: Some(80) }
{
...default,
expectedScheme: Some("http"),
expectedHost: Some(""),
expectedPort: Some(80),
}
)
testValid("google.com", { ...default, expectedPath: "google.com" })
testValid(
"//google.com/",
{ ...default, expectedHost: Some("google.com"), expectedPath: "/" }
)
testValid("google.com", { ...default, path: "google.com" })
testValid("//google.com/", { ...default, host: Some("google.com"), path: "/" })
testValid("", default)
testValid(
"google.com:80",
{ ...default, scheme: Some("google.com"), path: "80" }
{ ...default, expectedScheme: Some("google.com"), expectedPath: "80" }
)
testValid(".././..", { ...default, path: ".././.." })
testValid(".././..", { ...default, expectedPath: ".././.." })
testValid(
"http://?#",
{
...default,
scheme: Some("http"),
host: Some(""),
path: "",
query: Some(""),
fragment: Some(""),
expectedScheme: Some("http"),
expectedHost: Some(""),
expectedPath: "",
expectedQuery: Some(""),
expectedFragment: Some(""),
}
)

Expand All @@ -164,9 +187,9 @@ let testHostValid = (host, parsed="") => {
"scheme://" ++ host,
{
...default,
scheme: Some("scheme"),
host: Some(parsed),
string: "scheme://" ++ parsed,
expectedScheme: Some("scheme"),
expectedHost: Some(parsed),
expectedString: "scheme://" ++ parsed,
}
)
}
Expand Down Expand Up @@ -204,10 +227,10 @@ let testPath = (path, expected) => {
"scheme://domain" ++ path,
{
...default,
scheme: Some("scheme"),
host: Some("domain"),
path: expected,
string: "scheme://domain" ++ expected,
expectedScheme: Some("scheme"),
expectedHost: Some("domain"),
expectedPath: expected,
expectedString: "scheme://domain" ++ expected,
}
)
}
Expand Down
74 changes: 2 additions & 72 deletions stdlib/uri.gr
Expand Up @@ -23,7 +23,7 @@ include "result"
/**
* Represents a parsed RFC 3986 URI.
*/
abstract record Uri {
provide record Uri {
scheme: Option<String>,
userinfo: Option<String>,
host: Option<String>,
Expand Down Expand Up @@ -734,7 +734,7 @@ provide let parse = str => {
* Transforms a base URI and a URI reference into a target URI
*
* @param base: The base URI to resolve a URI reference on
* @param rel: The URI reference to apply onto the base
* @param ref: The URI reference to apply onto the base
* @returns `Ok(uri)` containing the target `Uri`, or `Err(err)` if input is malformed
*
* @example resolveReference(unwrap(parse("https://grain-lang.org/docs/stdlib/uri")), unwrap(parse("../intro"))) // https://grain-lang.org/docs/intro
Expand Down Expand Up @@ -1057,76 +1057,6 @@ provide let update =
return Ok({ scheme, userinfo, host, port, path, query, fragment })
}

/**
* Retrieves the scheme component of a `Uri`, if it has one
*
* @param uri: The `Uri` to get the scheme of
* @returns `Some(scheme)` containing the scheme of the `Uri`, or `None` if the `Uri` is a relative reference
*
* @since v0.6.0
*/
provide let scheme = uri => uri.scheme

/**
* Retrieves the userinfo component of a `Uri`, if it has one
*
* @param uri: The `Uri` to get the userinfo of
* @returns `Some(userinfo)` containing the userinfo of the `Uri`, or `None` if the `Uri` does not have one
*
* @since v0.6.0
*/
provide let userinfo = uri => uri.userinfo

/**
* Retrieves the host component of a `Uri`
*
* @param uri: The `Uri` to get the host of
* @returns `Some(host)` containing the host of the `Uri`, or `None` if the `Uri` does not have one
*
* @since v0.6.0
*/
provide let host = uri => uri.host

/**
* Retrieves the port component of a `Uri`, if it has one
*
* @param uri: The `Uri` to get the port of
* @returns `Some(port)` containing the port of the `Uri`, or `None` if the `Uri` is a relative reference
*
* @since v0.6.0
*/
provide let port = uri => uri.port

/**
* Retrieves the path component of a `Uri`
*
* @param uri: The `Uri` to get the path of
* @returns The path of the given `Uri`
*
* @since v0.6.0
*/
provide let path = uri => uri.path

/**
* Retrieves the query string component of a `Uri`, if it has one
*
* @param uri: The `Uri` to get the query string of
* @returns `Some(query)` containing the query string of the `Uri`, or `None` if the `Uri` does not have one
*
* @since v0.6.0
*/
provide let query = uri => uri.query

/**
* Retrieves the fragment component of a `Uri`, if it has one
*
* @param uri: The `Uri` to get the fragment of
* @returns `Some(fragment)` containing the fragment of the `Uri`, or `None` if the `Uri` does not have one
*
* @since v0.6.0
*/
provide let fragment = uri => uri.fragment

/**
* Determines whether or not a `Uri` has an authority (i.e. has a host component)
*
Expand Down

0 comments on commit 8462b35

Please sign in to comment.