diff options
-rw-r--r-- | src/gleam/uri.gleam | 34 | ||||
-rw-r--r-- | test/gleam/uri_test.gleam | 59 |
2 files changed, 45 insertions, 48 deletions
diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam index ed63292..f92f91a 100644 --- a/src/gleam/uri.gleam +++ b/src/gleam/uri.gleam @@ -9,22 +9,24 @@ import gleam/list import gleam/result +import gleam/option.{Option} import gleam/string import gleam/dynamic.{Dynamic} import gleam/map.{Map} +import gleam/function /// Type representing holding the parsed components of an URI. /// All components of a URI are optional, except the path. /// pub type Uri { Uri( - scheme: Result(String, Nil), - userinfo: Result(String, Nil), - host: Result(String, Nil), - port: Result(Int, Nil), + scheme: Option(String), + userinfo: Option(String), + host: Option(String), + port: Option(Int), path: String, - query: Result(String, Nil), - fragment: Result(String, Nil), + query: Option(String), + fragment: Option(String), ) } @@ -49,11 +51,11 @@ type UriKey { pub fn parse(string: String) -> Result(Uri, Nil) { try uri_map = dynamic.map(erl_parse(string)) |> result.nil_error - let get = fn(k, decoder: dynamic.Decoder(t)) { - try value = map.get(uri_map, dynamic.from(k)) - value - |> decoder - |> result.nil_error + let get = fn(k: UriKey, decode_type: dynamic.Decoder(t)) -> Option(t) { + uri_map + |> map.get(dynamic.from(k)) + |> result.then(function.compose(decode_type, result.nil_error)) + |> option.from_result } let uri = Uri( @@ -61,7 +63,7 @@ pub fn parse(string: String) -> Result(Uri, Nil) { userinfo: get(Userinfo, dynamic.string), host: get(Host, dynamic.string), port: get(Port, dynamic.int), - path: result.unwrap(get(Path, dynamic.string), ""), + path: option.unwrap(get(Path, dynamic.string), ""), query: get(Query, dynamic.string), fragment: get(Fragment, dynamic.string), ) @@ -141,8 +143,10 @@ external fn erl_to_string(Map(UriKey, Dynamic)) -> Dynamic = /// The opposite operation is `uri.parse`. /// pub fn to_string(uri: Uri) -> String { - let field = fn(key: UriKey, value: Result(anything, Nil)) { - result.map(value, fn(value) { tuple(key, dynamic.from(value)) }) + let field = fn(key: UriKey, value: Option(anything)) { + value + |> option.to_result(Nil) + |> result.map(fn(value) { tuple(key, dynamic.from(value)) }) } [ @@ -150,7 +154,7 @@ pub fn to_string(uri: Uri) -> String { field(Userinfo, uri.userinfo), field(Host, uri.host), field(Port, uri.port), - field(Path, Ok(uri.path)), + field(Path, option.Some(uri.path)), field(Query, uri.query), field(Fragment, uri.fragment), ] diff --git a/test/gleam/uri_test.gleam b/test/gleam/uri_test.gleam index edb7fce..49b4c02 100644 --- a/test/gleam/uri_test.gleam +++ b/test/gleam/uri_test.gleam @@ -1,39 +1,40 @@ import gleam/uri import gleam/should +import gleam/option.{Option, Some, None} pub fn full_parse_test() { let Ok( parsed, ) = uri.parse("https://foo:bar@example.com:1234/path?query=true#fragment") - should.equal(parsed.scheme, Ok("https")) - should.equal(parsed.userinfo, Ok("foo:bar")) - should.equal(parsed.host, Ok("example.com")) - should.equal(parsed.port, Ok(1234)) + should.equal(parsed.scheme, Some("https")) + should.equal(parsed.userinfo, Some("foo:bar")) + should.equal(parsed.host, Some("example.com")) + should.equal(parsed.port, Some(1234)) should.equal(parsed.path, "/path") - should.equal(parsed.query, Ok("query=true")) - should.equal(parsed.fragment, Ok("fragment")) + should.equal(parsed.query, Some("query=true")) + should.equal(parsed.fragment, Some("fragment")) } pub fn parse_only_path_test() { let Ok(parsed) = uri.parse("") - should.equal(parsed.scheme, Error(Nil)) - should.equal(parsed.userinfo, Error(Nil)) - should.equal(parsed.host, Error(Nil)) - should.equal(parsed.port, Error(Nil)) + should.equal(parsed.scheme, None) + should.equal(parsed.userinfo, None) + should.equal(parsed.host, None) + should.equal(parsed.port, None) should.equal(parsed.path, "") - should.equal(parsed.query, Error(Nil)) - should.equal(parsed.fragment, Error(Nil)) + should.equal(parsed.query, None) + should.equal(parsed.fragment, None) } pub fn parse_only_host_test() { let Ok(parsed) = uri.parse("//") - should.equal(parsed.scheme, Error(Nil)) - should.equal(parsed.userinfo, Error(Nil)) - should.equal(parsed.host, Ok("")) - should.equal(parsed.port, Error(Nil)) + should.equal(parsed.scheme, None) + should.equal(parsed.userinfo, None) + should.equal(parsed.host, Some("")) + should.equal(parsed.port, None) should.equal(parsed.path, "") - should.equal(parsed.query, Error(Nil)) - should.equal(parsed.fragment, Error(Nil)) + should.equal(parsed.query, None) + should.equal(parsed.fragment, None) } pub fn error_parsing_uri_test() { @@ -42,13 +43,13 @@ pub fn error_parsing_uri_test() { pub fn full_uri_to_string_test() { let test_uri = uri.Uri( - Ok("https"), - Ok("foo:bar"), - Ok("example.com"), - Ok(1234), + Some("https"), + Some("foo:bar"), + Some("example.com"), + Some(1234), "/path", - Ok("query=true"), - Ok("fragment"), + Some("query=true"), + Some("fragment"), ) should.equal( uri.to_string(test_uri), @@ -57,15 +58,7 @@ pub fn full_uri_to_string_test() { } pub fn path_only_uri_to_string_test() { - let test_uri = uri.Uri( - Error(Nil), - Error(Nil), - Error(Nil), - Error(Nil), - "/", - Error(Nil), - Error(Nil), - ) + let test_uri = uri.Uri(None, None, None, None, "/", None, None) should.equal(uri.to_string(test_uri), "/") } |