feat: Refactor and added normali(s/z)e
This commit is contained in:
@@ -14,6 +14,7 @@ version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
gleam_stdlib = ">= 0.44.0 and < 2.0.0"
|
||||
splitter = ">= 1.1.0 and < 2.0.0"
|
||||
|
||||
[dev-dependencies]
|
||||
gleeunit = ">= 1.0.0 and < 2.0.0"
|
||||
|
||||
@@ -22,6 +22,7 @@ packages = [
|
||||
{ name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" },
|
||||
{ name = "simplifile", version = "2.3.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "0A868DAC6063D9E983477981839810DC2E553285AB4588B87E3E9C96A7FB4CB4" },
|
||||
{ name = "snag", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "7E9F06390040EB5FAB392CE642771484136F2EC103A92AE11BA898C8167E6E17" },
|
||||
{ name = "splitter", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "splitter", source = "hex", outer_checksum = "05564A381580395DCDEFF4F88A64B021E8DAFA6540AE99B4623962F52976AA9D" },
|
||||
{ name = "startest", version = "0.7.0", build_tools = ["gleam"], requirements = ["argv", "bigben", "birl", "exception", "gleam_community_ansi", "gleam_erlang", "gleam_javascript", "gleam_regexp", "gleam_stdlib", "glint", "simplifile", "tom"], otp_app = "startest", source = "hex", outer_checksum = "71B9CB82C4B8779A4BD54C7151DF7D0B0F778D0DDE805B782B44EFA7BA8F50DA" },
|
||||
{ name = "tom", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "74D0C5A3761F7A7D06994755D4D5AD854122EF8E9F9F76A3E7547606D8C77091" },
|
||||
]
|
||||
@@ -29,4 +30,5 @@ packages = [
|
||||
[requirements]
|
||||
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
|
||||
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
|
||||
splitter = { version = ">= 1.1.0 and < 2.0.0" }
|
||||
startest = { version = ">= 0.7.0 and < 1.0.0" }
|
||||
|
||||
850
src/internal/parser.gleam
Normal file
850
src/internal/parser.gleam
Normal file
@@ -0,0 +1,850 @@
|
||||
import gleam/bool
|
||||
import gleam/int
|
||||
import gleam/list.{Continue, Stop}
|
||||
import gleam/option.{None, Some}
|
||||
import gleam/result
|
||||
import gleam/string
|
||||
|
||||
import types.{type Uri, Uri, empty_uri}
|
||||
|
||||
pub fn parse(uri: String) -> Result(Uri, Nil) {
|
||||
case parse_scheme(uri) {
|
||||
Ok(#(scheme, rest)) -> {
|
||||
use #(rel_part, rest) <- result.try(parse_hier_part(rest))
|
||||
|
||||
use #(query, rest) <- result.try(parse_query(rest))
|
||||
|
||||
use #(fragment, rest) <- result.try(parse_fragment(rest))
|
||||
|
||||
case rest {
|
||||
"" -> Ok(combine_uris([scheme, rel_part, query, fragment]))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
Error(_) -> {
|
||||
use #(rel_part, rest) <- result.try(parse_relative_part(uri))
|
||||
|
||||
use #(query, rest) <- result.try(parse_query(rest))
|
||||
|
||||
use #(fragment, rest) <- result.try(parse_fragment(rest))
|
||||
|
||||
case rest {
|
||||
"" -> Ok(combine_uris([rel_part, query, fragment]))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_query(str: String) -> Result(#(Uri, String), Nil) {
|
||||
case str {
|
||||
"?" <> rest -> {
|
||||
let #(query, rest) = get_multiple_optional(parse_query_fragment, rest)
|
||||
Ok(#(Uri(..empty_uri, query: Some(query)), rest))
|
||||
}
|
||||
_ -> Ok(#(empty_uri, str))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_fragment(str: String) -> Result(#(Uri, String), Nil) {
|
||||
case str {
|
||||
"#" <> rest -> {
|
||||
let #(fragment, rest) = get_multiple_optional(parse_query_fragment, rest)
|
||||
Ok(#(Uri(..empty_uri, fragment: Some(fragment)), rest))
|
||||
}
|
||||
_ -> Ok(#(empty_uri, str))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_hier_part(str: String) -> Result(#(Uri, String), Nil) {
|
||||
list.fold_until(
|
||||
[parse_authority, parse_absolute, parse_rootless, parse_empty],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_relative_part(str: String) -> Result(#(Uri, String), Nil) {
|
||||
list.fold_until(
|
||||
[parse_authority, parse_absolute, parse_noscheme, parse_empty],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_absolute(str: String) -> Result(#(Uri, String), Nil) {
|
||||
case str {
|
||||
"/" <> rest -> {
|
||||
let assert Ok(#(seg, rest)) =
|
||||
parse_optional(rest, parse_this_then(
|
||||
[
|
||||
do_parse_segment_nz,
|
||||
get_multiple_optional_result(
|
||||
fn(str) {
|
||||
case str {
|
||||
"/" <> rest -> {
|
||||
do_parse_segment(rest, do_parse_pchar, "/")
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
_,
|
||||
),
|
||||
],
|
||||
_,
|
||||
))
|
||||
|
||||
Ok(#(Uri(None, None, None, None, "/" <> seg, None, None), rest))
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_rootless(str: String) -> Result(#(Uri, String), Nil) {
|
||||
use #(seg1, rest) <- result.try(do_parse_segment_nz(str))
|
||||
|
||||
let #(segs, rest) =
|
||||
get_multiple_optional(
|
||||
fn(str) {
|
||||
case str {
|
||||
"/" <> rest -> {
|
||||
do_parse_segment(rest, do_parse_pchar, "/")
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
rest,
|
||||
)
|
||||
|
||||
Ok(#(Uri(None, None, None, None, seg1 <> segs, None, None), rest))
|
||||
}
|
||||
|
||||
fn parse_noscheme(str: String) -> Result(#(Uri, String), Nil) {
|
||||
use #(seg1, rest) <- result.try(do_parse_segment_nz_nc(str))
|
||||
|
||||
let #(segs, rest) =
|
||||
get_multiple_optional(
|
||||
fn(str) {
|
||||
case str {
|
||||
"/" <> rest -> {
|
||||
do_parse_segment(rest, do_parse_pchar, "/")
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
rest,
|
||||
)
|
||||
|
||||
Ok(#(Uri(None, None, None, None, seg1 <> segs, None, None), rest))
|
||||
}
|
||||
|
||||
fn parse_optional(str, opt_fn) {
|
||||
case opt_fn(str) {
|
||||
Error(Nil) -> Ok(#("", str))
|
||||
Ok(r) -> Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
fn get_multiple_optional_result(opt_fn, str: String) {
|
||||
get_multiple_optional(opt_fn, str) |> Ok
|
||||
}
|
||||
|
||||
fn get_multiple_optional(opt_fn, str: String) {
|
||||
case get_multiple(opt_fn, str) {
|
||||
Error(_) -> #("", str)
|
||||
Ok(r) -> r
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_empty(str: String) -> Result(#(Uri, String), Nil) {
|
||||
Ok(#(Uri(None, None, None, None, "", None, None), str))
|
||||
}
|
||||
|
||||
fn parse_authority(str: String) -> Result(#(Uri, String), Nil) {
|
||||
case str {
|
||||
"//" <> rest -> {
|
||||
parse_authority_part(rest) |> echo
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_authority_part(str: String) -> Result(#(Uri, String), Nil) {
|
||||
let #(ui, rest) = case parse_userinfo(str, "") {
|
||||
Ok(#(ui, rest)) -> #(Some(ui), rest)
|
||||
Error(_) -> #(None, str)
|
||||
}
|
||||
|
||||
use #(host, rest) <- result.try(parse_host(rest))
|
||||
|
||||
let #(port, rest) = case parse_port(rest) {
|
||||
Ok(#("", rest)) -> #(None, rest)
|
||||
Error(_) -> #(None, rest)
|
||||
Ok(#(port, rest)) -> {
|
||||
let assert Ok(port) = int.parse(port)
|
||||
#(Some(port), rest)
|
||||
}
|
||||
}
|
||||
|
||||
let #(path, rest) = parse_abs_empty(rest)
|
||||
|
||||
Ok(#(Uri(None, ui, Some(host), port, path, None, None), rest))
|
||||
}
|
||||
|
||||
fn parse_port(str: String) {
|
||||
case str {
|
||||
":" <> rest -> {
|
||||
Ok(parse_digits(rest, ""))
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_digits(str: String, digits: String) {
|
||||
case parse_digit(str) {
|
||||
Ok(#(d, rest)) -> {
|
||||
parse_digits(rest, digits <> d)
|
||||
}
|
||||
Error(_) -> #(digits, str)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_host(str: String) {
|
||||
list.fold_until(
|
||||
[parse_ip_literal, parse_ipv4, parse_reg_name],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_ip_literal(str: String) {
|
||||
case str {
|
||||
"[" <> rest -> {
|
||||
use #(ip, rest) <- result.try(list.fold_until(
|
||||
[parse_ipv6, parse_ipfuture],
|
||||
Error(Nil),
|
||||
get_parser_fn(rest),
|
||||
))
|
||||
case rest {
|
||||
"]" <> rest -> Ok(#(ip, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_ipv6(str: String) {
|
||||
list.fold_until(
|
||||
[
|
||||
parse_this_then([parse_min_max(_, 6, 6, parse_h16_colon), parse_ls32], _),
|
||||
parse_this_then(
|
||||
[parse_colons, parse_min_max(_, 5, 5, parse_h16_colon), parse_ls32],
|
||||
_,
|
||||
),
|
||||
parse_this_then(
|
||||
[
|
||||
parse_optional(_, parse_h16),
|
||||
parse_colons,
|
||||
parse_min_max(_, 4, 4, parse_h16_colon),
|
||||
parse_ls32,
|
||||
],
|
||||
_,
|
||||
),
|
||||
parse_this_then(
|
||||
[
|
||||
parse_optional(_, parse_this_then([parse_h16s(_, 1), parse_h16], _)),
|
||||
parse_colons,
|
||||
parse_min_max(_, 3, 3, parse_h16_colon),
|
||||
parse_ls32,
|
||||
],
|
||||
_,
|
||||
),
|
||||
parse_this_then(
|
||||
[
|
||||
parse_optional(_, parse_this_then([parse_h16s(_, 2), parse_h16], _)),
|
||||
parse_colons,
|
||||
parse_min_max(_, 2, 2, parse_h16_colon),
|
||||
parse_ls32,
|
||||
],
|
||||
_,
|
||||
),
|
||||
parse_this_then(
|
||||
[
|
||||
parse_optional(_, parse_this_then([parse_h16s(_, 3), parse_h16], _)),
|
||||
parse_colons,
|
||||
parse_min_max(_, 1, 1, parse_h16_colon),
|
||||
parse_ls32,
|
||||
],
|
||||
_,
|
||||
),
|
||||
parse_this_then(
|
||||
[
|
||||
parse_optional(_, parse_this_then([parse_h16s(_, 4), parse_h16], _)),
|
||||
parse_colons,
|
||||
parse_ls32,
|
||||
],
|
||||
_,
|
||||
),
|
||||
parse_this_then(
|
||||
[
|
||||
parse_optional(_, parse_this_then([parse_h16s(_, 5), parse_h16], _)),
|
||||
parse_colons,
|
||||
parse_h16,
|
||||
],
|
||||
_,
|
||||
),
|
||||
parse_this_then(
|
||||
[
|
||||
parse_optional(_, parse_this_then([parse_h16s(_, 6), parse_h16], _)),
|
||||
parse_colons,
|
||||
],
|
||||
_,
|
||||
),
|
||||
],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_h16s(str: String, max) {
|
||||
parse_min_max(str, 0, max, parse_h16_colon)
|
||||
}
|
||||
|
||||
fn parse_colons(str: String) {
|
||||
case str {
|
||||
"::" <> rest -> Ok(#("::", rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_this_then(
|
||||
parsers: List(fn(String) -> Result(#(String, String), Nil)),
|
||||
str: String,
|
||||
) {
|
||||
list.fold_until(parsers, Ok(#("", str)), fn(acc, parser) {
|
||||
let assert Ok(#(res, str)) = acc
|
||||
case parser(str) {
|
||||
Ok(#(res2, rest)) -> {
|
||||
Continue(Ok(#(res <> res2, rest)))
|
||||
}
|
||||
Error(Nil) -> Stop(Error(Nil))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_ls32(str: String) -> Result(#(String, String), Nil) {
|
||||
list.fold_until([parse_h16_pair, parse_ipv4], Error(Nil), get_parser_fn(str))
|
||||
}
|
||||
|
||||
fn parse_h16_pair(str: String) {
|
||||
use #(h16a, rest) <- result.try(parse_h16(str))
|
||||
case rest {
|
||||
":" <> rest -> {
|
||||
use #(h16b, rest) <- result.try(parse_h16(rest))
|
||||
Ok(#(h16a <> ":" <> h16b, rest))
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_h16(str: String) {
|
||||
parse_hex_digits(str, 1, 4)
|
||||
}
|
||||
|
||||
fn parse_h16_colon(str: String) {
|
||||
use #(h16, rest) <- result.try(parse_h16(str))
|
||||
case rest {
|
||||
":" <> rest -> Ok(#(h16 <> ":", rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_ipfuture(str: String) {
|
||||
Error(Nil)
|
||||
}
|
||||
|
||||
fn get_multiple(
|
||||
to_run: fn(String) -> Result(#(String, String), Nil),
|
||||
str: String,
|
||||
) -> Result(#(String, String), Nil) {
|
||||
case do_get_multiple(to_run, str, "") {
|
||||
Ok(#("", _)) | Error(Nil) -> Error(Nil)
|
||||
Ok(#(r, rest)) -> Ok(#(r, rest))
|
||||
}
|
||||
}
|
||||
|
||||
fn do_get_multiple(
|
||||
to_run: fn(String) -> Result(#(String, String), Nil),
|
||||
str: String,
|
||||
ret: String,
|
||||
) -> Result(#(String, String), Nil) {
|
||||
case str {
|
||||
"" -> Ok(#(ret, str))
|
||||
_ ->
|
||||
case to_run(str) {
|
||||
Ok(#(r, rest)) -> do_get_multiple(to_run, rest, ret <> r)
|
||||
Error(_) -> Ok(#(ret, str))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_query_fragment(str: String) {
|
||||
list.fold_until(
|
||||
[
|
||||
do_parse_pchar,
|
||||
fn(str: String) {
|
||||
case str {
|
||||
"/" as l <> rest | "?" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_abs_empty(str: String) -> #(String, String) {
|
||||
get_multiple_optional(
|
||||
fn(str) {
|
||||
case str {
|
||||
"/" <> rest -> {
|
||||
do_parse_segment(rest, do_parse_pchar, "/")
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
str,
|
||||
)
|
||||
}
|
||||
|
||||
fn do_parse_segment(
|
||||
str: String,
|
||||
char_fn,
|
||||
segment: String,
|
||||
) -> Result(#(String, String), Nil) {
|
||||
case char_fn(str) {
|
||||
Error(Nil) | Ok(#("", _)) -> Ok(#(segment, str))
|
||||
Ok(#(l, rest)) -> do_parse_segment(rest, char_fn, segment <> l)
|
||||
}
|
||||
}
|
||||
|
||||
fn do_parse_segment_nz(str: String) {
|
||||
use #(char1, rest) <- result.try(do_parse_pchar(str))
|
||||
|
||||
use #(chars, rest) <- result.try(do_parse_segment(rest, do_parse_pchar, char1))
|
||||
|
||||
Ok(#(chars, rest))
|
||||
}
|
||||
|
||||
fn do_parse_segment_nz_nc(str: String) {
|
||||
use #(char1, rest) <- result.try(do_parse_pchar_nc(str))
|
||||
|
||||
use #(chars, rest) <- result.try(do_parse_segment(
|
||||
rest,
|
||||
do_parse_pchar_nc,
|
||||
char1,
|
||||
))
|
||||
|
||||
Ok(#(chars, rest))
|
||||
}
|
||||
|
||||
fn do_parse_pchar(str: String) {
|
||||
list.fold_until(
|
||||
[
|
||||
parse_unreserved,
|
||||
parse_pct_encoded,
|
||||
parse_sub_delim,
|
||||
fn(str: String) {
|
||||
case str {
|
||||
":" as l <> rest | "@" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
}
|
||||
|
||||
fn do_parse_pchar_nc(str: String) {
|
||||
list.fold_until(
|
||||
[
|
||||
parse_unreserved,
|
||||
parse_pct_encoded,
|
||||
parse_sub_delim,
|
||||
fn(str: String) {
|
||||
case str {
|
||||
"@" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
}
|
||||
|
||||
fn parse_reg_name(str: String) {
|
||||
// can't error
|
||||
|
||||
case do_parse_reg_name(str, "") |> echo {
|
||||
Error(Nil) -> Ok(#("", str))
|
||||
Ok(#(reg_name, rest)) -> Ok(#(reg_name, rest))
|
||||
}
|
||||
}
|
||||
|
||||
fn do_parse_reg_name(str: String, reg_name: String) {
|
||||
case
|
||||
list.fold_until(
|
||||
[parse_unreserved, parse_pct_encoded, parse_sub_delim],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
{
|
||||
Error(Nil) | Ok(#("", _)) -> Ok(#(reg_name, str))
|
||||
Ok(#(l, rest)) -> do_parse_reg_name(rest, reg_name <> l)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_pct_encoded(str: String) {
|
||||
case str {
|
||||
"%" <> rest -> {
|
||||
use #(hex1, rest) <- result.try(parse_hex_digit(rest))
|
||||
use #(hex2, rest) <- result.try(parse_hex_digit(rest))
|
||||
|
||||
Ok(#("%" <> hex1 <> hex2, rest))
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_sub_delim(str: String) {
|
||||
case str {
|
||||
"!" as l <> rest
|
||||
| "$" as l <> rest
|
||||
| "&" as l <> rest
|
||||
| "'" as l <> rest
|
||||
| "(" as l <> rest
|
||||
| ")" as l <> rest
|
||||
| "*" as l <> rest
|
||||
| "+" as l <> rest
|
||||
| "," as l <> rest
|
||||
| ";" as l <> rest
|
||||
| "=" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_ipv4(str: String) {
|
||||
use #(oct1, rest) <- result.try(parse_dec_octet(str))
|
||||
use rest <- result.try(case rest {
|
||||
"." <> rest -> Ok(rest)
|
||||
_ -> Error(Nil)
|
||||
})
|
||||
use #(oct2, rest) <- result.try(parse_dec_octet(rest))
|
||||
use rest <- result.try(case rest {
|
||||
"." <> rest -> Ok(rest)
|
||||
_ -> Error(Nil)
|
||||
})
|
||||
use #(oct3, rest) <- result.try(parse_dec_octet(rest))
|
||||
use rest <- result.try(case rest {
|
||||
"." <> rest -> Ok(rest)
|
||||
_ -> Error(Nil)
|
||||
})
|
||||
use #(oct4, rest) <- result.try(parse_dec_octet(rest))
|
||||
Ok(#(oct1 <> "." <> oct2 <> "." <> oct3 <> "." <> oct4, rest))
|
||||
}
|
||||
|
||||
fn parse_dec_octet(str: String) -> Result(#(String, String), Nil) {
|
||||
let matches = [
|
||||
["2", "5", "012345"],
|
||||
["2", "01234", "0123456789"],
|
||||
["1", "0123456789", "0123456789"],
|
||||
["123456789", "0123456789"],
|
||||
["0123456789"],
|
||||
]
|
||||
|
||||
list.fold_until(matches, Error(Nil), fn(_, chars) {
|
||||
case
|
||||
list.fold_until(chars, #("", str), fn(acc, charset) {
|
||||
let #(octet, str) = acc
|
||||
case string.pop_grapheme(str) {
|
||||
Error(_) -> Stop(#("", ""))
|
||||
Ok(#(char, rest)) -> {
|
||||
case string.contains(charset, char) {
|
||||
True -> Continue(#(octet <> char, rest))
|
||||
False -> Stop(#("", ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
{
|
||||
#("", _) -> Continue(Error(Nil))
|
||||
#(octet, rest) -> Stop(Ok(#(octet, rest)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_userinfo(
|
||||
str: String,
|
||||
userinfo: String,
|
||||
) -> Result(#(String, String), Nil) {
|
||||
case str {
|
||||
"@" <> rest -> Ok(#(userinfo, rest))
|
||||
"" -> Error(Nil)
|
||||
_ -> {
|
||||
use #(part, rest) <- result.try(list.fold_until(
|
||||
[
|
||||
parse_unreserved,
|
||||
parse_pct_encoded,
|
||||
parse_sub_delim,
|
||||
fn(str: String) {
|
||||
case str {
|
||||
":" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
))
|
||||
parse_userinfo(rest, userinfo <> part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_scheme(str: String) -> Result(#(Uri, String), Nil) {
|
||||
case parse_alpha(str) {
|
||||
Ok(#(first, rest)) -> {
|
||||
case do_parse_scheme(rest, first) {
|
||||
Error(_) -> Error(Nil)
|
||||
Ok(#(scheme, rest)) ->
|
||||
Ok(#(Uri(Some(scheme), None, None, None, "", None, None), rest))
|
||||
}
|
||||
}
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn do_parse_scheme(
|
||||
str: String,
|
||||
scheme: String,
|
||||
) -> Result(#(String, String), Nil) {
|
||||
case str {
|
||||
":" <> rest -> Ok(#(scheme, rest))
|
||||
"" -> Error(Nil)
|
||||
_ -> {
|
||||
use #(part, rest) <- result.try(list.fold_until(
|
||||
[
|
||||
parse_alpha,
|
||||
parse_digit,
|
||||
fn(str) {
|
||||
case str {
|
||||
"+" as l <> rest | "-" as l <> rest | "." as l <> rest ->
|
||||
Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
))
|
||||
do_parse_scheme(rest, scheme <> part)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_parser_fn(
|
||||
str: String,
|
||||
) -> fn(a, fn(String) -> Result(b, c)) -> list.ContinueOrStop(Result(b, Nil)) {
|
||||
fn(_, parse_fn) {
|
||||
case parse_fn(str) {
|
||||
Ok(r) -> Stop(Ok(r))
|
||||
Error(_) -> Continue(Error(Nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_min_max(str, min, max, parse_fn) {
|
||||
use <- bool.guard(when: min < 0 || max <= 0 || min > max, return: Error(Nil))
|
||||
case
|
||||
list.repeat("", max)
|
||||
|> list.fold_until(Ok(#("", str, 0)), fn(acc, _) {
|
||||
let assert Ok(#(hex, str, i)) = acc
|
||||
case parse_fn(str) {
|
||||
Error(_) ->
|
||||
case i < min {
|
||||
True -> Stop(Error(Nil))
|
||||
False -> Stop(Ok(#(hex, str, i)))
|
||||
}
|
||||
Ok(#(l, rest)) -> Continue(Ok(#(hex <> l, rest, i + 1)))
|
||||
}
|
||||
})
|
||||
{
|
||||
Error(_) -> Error(Nil)
|
||||
Ok(#(hex, str, _)) -> Ok(#(hex, str))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_hex_digits(str, min, max) {
|
||||
parse_min_max(str, min, max, parse_hex_digit)
|
||||
}
|
||||
|
||||
pub fn parse_hex_digit(str) {
|
||||
case str {
|
||||
"0" as l <> rest
|
||||
| "1" as l <> rest
|
||||
| "2" as l <> rest
|
||||
| "3" as l <> rest
|
||||
| "4" as l <> rest
|
||||
| "5" as l <> rest
|
||||
| "6" as l <> rest
|
||||
| "7" as l <> rest
|
||||
| "8" as l <> rest
|
||||
| "9" as l <> rest
|
||||
| "a" as l <> rest
|
||||
| "b" as l <> rest
|
||||
| "c" as l <> rest
|
||||
| "d" as l <> rest
|
||||
| "e" as l <> rest
|
||||
| "f" as l <> rest
|
||||
| "A" as l <> rest
|
||||
| "B" as l <> rest
|
||||
| "C" as l <> rest
|
||||
| "D" as l <> rest
|
||||
| "E" as l <> rest
|
||||
| "F" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_digit(str: String) -> Result(#(String, String), Nil) {
|
||||
case str {
|
||||
"0" as l <> rest
|
||||
| "1" as l <> rest
|
||||
| "2" as l <> rest
|
||||
| "3" as l <> rest
|
||||
| "4" as l <> rest
|
||||
| "5" as l <> rest
|
||||
| "6" as l <> rest
|
||||
| "7" as l <> rest
|
||||
| "8" as l <> rest
|
||||
| "9" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_alpha(str: String) -> Result(#(String, String), Nil) {
|
||||
case str {
|
||||
"a" as l <> rest
|
||||
| "b" as l <> rest
|
||||
| "c" as l <> rest
|
||||
| "d" as l <> rest
|
||||
| "e" as l <> rest
|
||||
| "f" as l <> rest
|
||||
| "g" as l <> rest
|
||||
| "h" as l <> rest
|
||||
| "i" as l <> rest
|
||||
| "j" as l <> rest
|
||||
| "k" as l <> rest
|
||||
| "l" as l <> rest
|
||||
| "m" as l <> rest
|
||||
| "n" as l <> rest
|
||||
| "o" as l <> rest
|
||||
| "p" as l <> rest
|
||||
| "q" as l <> rest
|
||||
| "r" as l <> rest
|
||||
| "s" as l <> rest
|
||||
| "t" as l <> rest
|
||||
| "u" as l <> rest
|
||||
| "v" as l <> rest
|
||||
| "w" as l <> rest
|
||||
| "x" as l <> rest
|
||||
| "y" as l <> rest
|
||||
| "z" as l <> rest
|
||||
| "A" as l <> rest
|
||||
| "B" as l <> rest
|
||||
| "C" as l <> rest
|
||||
| "D" as l <> rest
|
||||
| "E" as l <> rest
|
||||
| "F" as l <> rest
|
||||
| "G" as l <> rest
|
||||
| "H" as l <> rest
|
||||
| "I" as l <> rest
|
||||
| "J" as l <> rest
|
||||
| "K" as l <> rest
|
||||
| "L" as l <> rest
|
||||
| "M" as l <> rest
|
||||
| "N" as l <> rest
|
||||
| "O" as l <> rest
|
||||
| "P" as l <> rest
|
||||
| "Q" as l <> rest
|
||||
| "R" as l <> rest
|
||||
| "S" as l <> rest
|
||||
| "T" as l <> rest
|
||||
| "U" as l <> rest
|
||||
| "V" as l <> rest
|
||||
| "W" as l <> rest
|
||||
| "X" as l <> rest
|
||||
| "Y" as l <> rest
|
||||
| "Z" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_unreserved(str: String) -> Result(#(String, String), Nil) {
|
||||
list.fold_until(
|
||||
[
|
||||
parse_alpha,
|
||||
parse_digit,
|
||||
fn(str) {
|
||||
case str {
|
||||
"_" as l <> rest
|
||||
| "-" as l <> rest
|
||||
| "." as l <> rest
|
||||
| "~" as l <> rest -> Ok(#(l, rest))
|
||||
_ -> Error(Nil)
|
||||
}
|
||||
},
|
||||
],
|
||||
Error(Nil),
|
||||
get_parser_fn(str),
|
||||
)
|
||||
}
|
||||
|
||||
fn combine_uris(uris: List(Uri)) -> Uri {
|
||||
list.fold(uris, Uri(None, None, None, None, "", None, None), fn(acc, uri) {
|
||||
let acc = case uri {
|
||||
Uri(Some(scheme), _, _, _, _, _, _) -> Uri(..acc, scheme: Some(scheme))
|
||||
_ -> acc
|
||||
}
|
||||
let acc = case uri {
|
||||
Uri(_, Some(userinfo), _, _, _, _, _) ->
|
||||
Uri(..acc, userinfo: Some(userinfo))
|
||||
_ -> acc
|
||||
}
|
||||
let acc = case uri {
|
||||
Uri(_, _, Some(host), _, _, _, _) -> Uri(..acc, host: Some(host))
|
||||
_ -> acc
|
||||
}
|
||||
let acc = case uri {
|
||||
Uri(_, _, _, Some(port), _, _, _) -> Uri(..acc, port: Some(port))
|
||||
_ -> acc
|
||||
}
|
||||
let acc = case uri {
|
||||
Uri(_, _, _, _, path, _, _) if path != "" -> Uri(..acc, path: path)
|
||||
_ -> acc
|
||||
}
|
||||
let acc = case uri {
|
||||
Uri(_, _, _, _, _, Some(query), _) -> Uri(..acc, query: Some(query))
|
||||
_ -> acc
|
||||
}
|
||||
case uri {
|
||||
Uri(_, _, _, _, _, _, Some(fragment)) ->
|
||||
Uri(..acc, fragment: Some(fragment))
|
||||
_ -> acc
|
||||
}
|
||||
})
|
||||
}
|
||||
15
src/types.gleam
Normal file
15
src/types.gleam
Normal file
@@ -0,0 +1,15 @@
|
||||
import gleam/option.{type Option, None}
|
||||
|
||||
pub type Uri {
|
||||
Uri(
|
||||
scheme: Option(String),
|
||||
userinfo: Option(String),
|
||||
host: Option(String),
|
||||
port: Option(Int),
|
||||
path: String,
|
||||
query: Option(String),
|
||||
fragment: Option(String),
|
||||
)
|
||||
}
|
||||
|
||||
pub const empty_uri = Uri(None, None, None, None, "", None, None)
|
||||
997
src/uri.gleam
997
src/uri.gleam
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,8 @@
|
||||
import gleam/option.{None, Some}
|
||||
import gleeunit/should
|
||||
import startest.{describe, it}
|
||||
import uri.{Uri}
|
||||
import types.{Uri}
|
||||
import uri
|
||||
|
||||
pub fn main() {
|
||||
startest.run(startest.default_config())
|
||||
@@ -10,26 +11,26 @@ pub fn main() {
|
||||
pub fn parse_scheme_tests() {
|
||||
describe("scheme parsing", [
|
||||
it("simple parse", fn() {
|
||||
uri.parse("") |> should.equal(Ok(uri.empty_uri))
|
||||
uri.parse("") |> should.equal(Ok(types.empty_uri))
|
||||
uri.parse("foo")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "foo")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "foo")))
|
||||
uri.parse("foo:")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, scheme: Some("foo"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, scheme: Some("foo"))))
|
||||
uri.parse("foo:bar:nisse")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), path: "bar:nisse"),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), path: "bar:nisse"),
|
||||
))
|
||||
uri.parse("foo://")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), host: Some("")),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), host: Some("")),
|
||||
))
|
||||
uri.parse("foo:///")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), host: Some(""), path: "/"),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), host: Some(""), path: "/"),
|
||||
))
|
||||
uri.parse("foo:////")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), host: Some(""), path: "//"),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), host: Some(""), path: "//"),
|
||||
))
|
||||
}),
|
||||
])
|
||||
@@ -40,34 +41,34 @@ pub fn parse_userinfo_tests() {
|
||||
it("simple parse", fn() {
|
||||
uri.parse("user:password@localhost")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("user"), path: "password@localhost"),
|
||||
Uri(..types.empty_uri, scheme: Some("user"), path: "password@localhost"),
|
||||
))
|
||||
uri.parse("user@")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "user@")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "user@")))
|
||||
uri.parse("/user@")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "/user@")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "/user@")))
|
||||
uri.parse("user@localhost")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "user@localhost")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "user@localhost")))
|
||||
uri.parse("//user@localhost")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, userinfo: Some("user"), host: Some("localhost")),
|
||||
Uri(..types.empty_uri, userinfo: Some("user"), host: Some("localhost")),
|
||||
))
|
||||
uri.parse("//user:password@localhost")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
userinfo: Some("user:password"),
|
||||
host: Some("localhost"),
|
||||
),
|
||||
))
|
||||
uri.parse("foo:/user@")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), path: "/user@"),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), path: "/user@"),
|
||||
))
|
||||
uri.parse("foo://user@localhost")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
userinfo: Some("user"),
|
||||
host: Some("localhost"),
|
||||
@@ -76,7 +77,7 @@ pub fn parse_userinfo_tests() {
|
||||
uri.parse("foo://user:password@localhost")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
userinfo: Some("user:password"),
|
||||
host: Some("localhost"),
|
||||
@@ -87,27 +88,27 @@ pub fn parse_userinfo_tests() {
|
||||
uri.parse("user:%E5%90%88@%E6%B0%97%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("user"),
|
||||
path: "%E5%90%88@%E6%B0%97%E9%81%93",
|
||||
),
|
||||
))
|
||||
uri.parse("%E5%90%88%E6%B0%97%E9%81%93@")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "%E5%90%88%E6%B0%97%E9%81%93@"),
|
||||
Uri(..types.empty_uri, path: "%E5%90%88%E6%B0%97%E9%81%93@"),
|
||||
))
|
||||
uri.parse("/%E5%90%88%E6%B0%97%E9%81%93@")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "/%E5%90%88%E6%B0%97%E9%81%93@"),
|
||||
Uri(..types.empty_uri, path: "/%E5%90%88%E6%B0%97%E9%81%93@"),
|
||||
))
|
||||
uri.parse("%E5%90%88@%E6%B0%97%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "%E5%90%88@%E6%B0%97%E9%81%93"),
|
||||
Uri(..types.empty_uri, path: "%E5%90%88@%E6%B0%97%E9%81%93"),
|
||||
))
|
||||
uri.parse("//%E5%90%88@%E6%B0%97%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("%E6%B0%97%E9%81%93"),
|
||||
userinfo: Some("%E5%90%88"),
|
||||
),
|
||||
@@ -115,7 +116,7 @@ pub fn parse_userinfo_tests() {
|
||||
uri.parse("//%E5%90%88:%E6%B0%97@%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("%E9%81%93"),
|
||||
userinfo: Some("%E5%90%88:%E6%B0%97"),
|
||||
),
|
||||
@@ -123,7 +124,7 @@ pub fn parse_userinfo_tests() {
|
||||
uri.parse("foo:/%E5%90%88%E6%B0%97%E9%81%93@")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
path: "/%E5%90%88%E6%B0%97%E9%81%93@",
|
||||
),
|
||||
@@ -131,7 +132,7 @@ pub fn parse_userinfo_tests() {
|
||||
uri.parse("foo://%E5%90%88@%E6%B0%97%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
userinfo: Some("%E5%90%88"),
|
||||
host: Some("%E6%B0%97%E9%81%93"),
|
||||
@@ -140,7 +141,7 @@ pub fn parse_userinfo_tests() {
|
||||
uri.parse("foo://%E5%90%88:%E6%B0%97@%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
userinfo: Some("%E5%90%88:%E6%B0%97"),
|
||||
host: Some("%E9%81%93"),
|
||||
@@ -156,15 +157,15 @@ pub fn parse_host_tests() {
|
||||
describe("host parsing", [
|
||||
it("simple parse", fn() {
|
||||
uri.parse("//hostname")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some("hostname"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, host: Some("hostname"))))
|
||||
uri.parse("foo://hostname")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), host: Some("hostname")),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), host: Some("hostname")),
|
||||
))
|
||||
uri.parse("foo://user@hostname")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
userinfo: Some("user"),
|
||||
host: Some("hostname"),
|
||||
@@ -173,54 +174,58 @@ pub fn parse_host_tests() {
|
||||
}),
|
||||
it("ipv4 parse", fn() {
|
||||
uri.parse("//127.0.0.1")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some("127.0.0.1"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, host: Some("127.0.0.1"))))
|
||||
uri.parse("//127.0.0.1/over/there")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("127.0.0.1"), path: "/over/there"),
|
||||
Uri(..types.empty_uri, host: Some("127.0.0.1"), path: "/over/there"),
|
||||
))
|
||||
uri.parse("//127.0.0.1?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("127.0.0.1"),
|
||||
query: Some("name=ferret"),
|
||||
),
|
||||
))
|
||||
uri.parse("//127.0.0.1#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("127.0.0.1"), fragment: Some("nose")),
|
||||
Uri(..types.empty_uri, host: Some("127.0.0.1"), fragment: Some("nose")),
|
||||
))
|
||||
|
||||
uri.parse("//127.0.0.x")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some("127.0.0.x"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, host: Some("127.0.0.x"))))
|
||||
uri.parse("//1227.0.0.1")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some("1227.0.0.1"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, host: Some("1227.0.0.1"))))
|
||||
}),
|
||||
it("ipv6 parse", fn() {
|
||||
uri.parse("//[::127.0.0.1]")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some("::127.0.0.1"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, host: Some("::127.0.0.1"))))
|
||||
uri.parse("//[2001:0db8:0000:0000:0000:0000:1428:07ab]")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("2001:0db8:0000:0000:0000:0000:1428:07ab"),
|
||||
),
|
||||
))
|
||||
uri.parse("//[::127.0.0.1]/over/there")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("::127.0.0.1"), path: "/over/there"),
|
||||
Uri(..types.empty_uri, host: Some("::127.0.0.1"), path: "/over/there"),
|
||||
))
|
||||
uri.parse("//[::127.0.0.1]?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("::127.0.0.1"),
|
||||
query: Some("name=ferret"),
|
||||
),
|
||||
))
|
||||
uri.parse("//[::127.0.0.1]#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("::127.0.0.1"), fragment: Some("nose")),
|
||||
Uri(
|
||||
..types.empty_uri,
|
||||
host: Some("::127.0.0.1"),
|
||||
fragment: Some("nose"),
|
||||
),
|
||||
))
|
||||
|
||||
uri.parse("//[::127.0.0.x]") |> should.be_error
|
||||
@@ -235,21 +240,23 @@ pub fn parse_port_tests() {
|
||||
describe("port parsing", [
|
||||
it("simple parse", fn() {
|
||||
uri.parse("/:8042")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "/:8042")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "/:8042")))
|
||||
uri.parse("//:8042")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some(""), port: Some(8042))))
|
||||
|> should.equal(Ok(
|
||||
Uri(..types.empty_uri, host: Some(""), port: Some(8042)),
|
||||
))
|
||||
uri.parse("//example.com:8042")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("example.com"), port: Some(8042)),
|
||||
Uri(..types.empty_uri, host: Some("example.com"), port: Some(8042)),
|
||||
))
|
||||
uri.parse("foo:/:8042")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), path: "/:8042"),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), path: "/:8042"),
|
||||
))
|
||||
uri.parse("foo://:8042")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some(""),
|
||||
port: Some(8042),
|
||||
@@ -258,7 +265,7 @@ pub fn parse_port_tests() {
|
||||
uri.parse("foo://example.com:8042")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
port: Some(8042),
|
||||
@@ -269,23 +276,25 @@ pub fn parse_port_tests() {
|
||||
}),
|
||||
it("undefined port", fn() {
|
||||
uri.parse("/:")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "/:")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "/:")))
|
||||
uri.parse("//:")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some(""), port: None)))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, host: Some(""), port: None)))
|
||||
uri.parse("//example.com:")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("example.com"), port: None),
|
||||
Uri(..types.empty_uri, host: Some("example.com"), port: None),
|
||||
))
|
||||
uri.parse("foo:/:")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, scheme: Some("foo"), path: "/:")))
|
||||
|> should.equal(Ok(
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), path: "/:"),
|
||||
))
|
||||
uri.parse("foo://:")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), host: Some(""), port: None),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), host: Some(""), port: None),
|
||||
))
|
||||
uri.parse("foo://example.com:")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
port: None,
|
||||
@@ -301,17 +310,17 @@ pub fn parse_path_tests() {
|
||||
describe("path parsing", [
|
||||
it("simple parse", fn() {
|
||||
uri.parse("over/there")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "over/there")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "over/there")))
|
||||
uri.parse("/over/there")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "/over/there")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "/over/there")))
|
||||
uri.parse("foo:/over/there")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), path: "/over/there"),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), path: "/over/there"),
|
||||
))
|
||||
uri.parse("foo://example.com/over/there")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
path: "/over/there",
|
||||
@@ -320,7 +329,7 @@ pub fn parse_path_tests() {
|
||||
uri.parse("foo://example.com:8042/over/there")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
port: Some(8042),
|
||||
@@ -336,12 +345,12 @@ pub fn parse_query_tests() {
|
||||
it("simple parse", fn() {
|
||||
uri.parse("foo:?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), query: Some("name=ferret")),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), query: Some("name=ferret")),
|
||||
))
|
||||
uri.parse("foo:over/there?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
path: "over/there",
|
||||
query: Some("name=ferret"),
|
||||
@@ -350,7 +359,7 @@ pub fn parse_query_tests() {
|
||||
uri.parse("foo:/over/there?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
path: "/over/there",
|
||||
query: Some("name=ferret"),
|
||||
@@ -359,7 +368,7 @@ pub fn parse_query_tests() {
|
||||
uri.parse("foo://example.com?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
query: Some("name=ferret"),
|
||||
@@ -368,7 +377,7 @@ pub fn parse_query_tests() {
|
||||
uri.parse("foo://example.com/?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
path: "/",
|
||||
@@ -378,24 +387,24 @@ pub fn parse_query_tests() {
|
||||
|
||||
uri.parse("?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "", query: Some("name=ferret")),
|
||||
Uri(..types.empty_uri, path: "", query: Some("name=ferret")),
|
||||
))
|
||||
uri.parse("over/there?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "over/there", query: Some("name=ferret")),
|
||||
Uri(..types.empty_uri, path: "over/there", query: Some("name=ferret")),
|
||||
))
|
||||
uri.parse("/?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "/", query: Some("name=ferret")),
|
||||
Uri(..types.empty_uri, path: "/", query: Some("name=ferret")),
|
||||
))
|
||||
uri.parse("/over/there?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "/over/there", query: Some("name=ferret")),
|
||||
Uri(..types.empty_uri, path: "/over/there", query: Some("name=ferret")),
|
||||
))
|
||||
uri.parse("//example.com?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("example.com"),
|
||||
query: Some("name=ferret"),
|
||||
),
|
||||
@@ -403,7 +412,7 @@ pub fn parse_query_tests() {
|
||||
uri.parse("//example.com/?name=ferret")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("example.com"),
|
||||
path: "/",
|
||||
query: Some("name=ferret"),
|
||||
@@ -414,7 +423,7 @@ pub fn parse_query_tests() {
|
||||
uri.parse("foo://example.com/?name=%E5%90%88%E6%B0%97%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
path: "/",
|
||||
@@ -424,7 +433,7 @@ pub fn parse_query_tests() {
|
||||
uri.parse("//example.com/?name=%E5%90%88%E6%B0%97%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("example.com"),
|
||||
path: "/",
|
||||
query: Some("name=%E5%90%88%E6%B0%97%E9%81%93"),
|
||||
@@ -439,12 +448,12 @@ pub fn parse_fragment_tests() {
|
||||
it("simple parse", fn() {
|
||||
uri.parse("foo:#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("foo"), fragment: Some("nose")),
|
||||
Uri(..types.empty_uri, scheme: Some("foo"), fragment: Some("nose")),
|
||||
))
|
||||
uri.parse("foo:over/there#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
path: "over/there",
|
||||
fragment: Some("nose"),
|
||||
@@ -453,7 +462,7 @@ pub fn parse_fragment_tests() {
|
||||
uri.parse("foo:/over/there#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
path: "/over/there",
|
||||
fragment: Some("nose"),
|
||||
@@ -462,7 +471,7 @@ pub fn parse_fragment_tests() {
|
||||
uri.parse("foo://example.com#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
fragment: Some("nose"),
|
||||
@@ -471,7 +480,7 @@ pub fn parse_fragment_tests() {
|
||||
uri.parse("foo://example.com/#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
path: "/",
|
||||
@@ -481,7 +490,7 @@ pub fn parse_fragment_tests() {
|
||||
uri.parse("foo://example.com#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
fragment: Some("nose"),
|
||||
@@ -489,27 +498,31 @@ pub fn parse_fragment_tests() {
|
||||
))
|
||||
|
||||
uri.parse("#nose")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, fragment: Some("nose"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, fragment: Some("nose"))))
|
||||
uri.parse("over/there#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "over/there", fragment: Some("nose")),
|
||||
Uri(..types.empty_uri, path: "over/there", fragment: Some("nose")),
|
||||
))
|
||||
uri.parse("/#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "/", fragment: Some("nose")),
|
||||
Uri(..types.empty_uri, path: "/", fragment: Some("nose")),
|
||||
))
|
||||
uri.parse("/over/there#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, path: "/over/there", fragment: Some("nose")),
|
||||
Uri(..types.empty_uri, path: "/over/there", fragment: Some("nose")),
|
||||
))
|
||||
uri.parse("//example.com#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("example.com"), fragment: Some("nose")),
|
||||
Uri(
|
||||
..types.empty_uri,
|
||||
host: Some("example.com"),
|
||||
fragment: Some("nose"),
|
||||
),
|
||||
))
|
||||
uri.parse("//example.com/#nose")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("example.com"),
|
||||
path: "/",
|
||||
fragment: Some("nose"),
|
||||
@@ -520,7 +533,7 @@ pub fn parse_fragment_tests() {
|
||||
uri.parse("foo://example.com#%E5%90%88%E6%B0%97%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some("example.com"),
|
||||
fragment: Some("%E5%90%88%E6%B0%97%E9%81%93"),
|
||||
@@ -529,7 +542,7 @@ pub fn parse_fragment_tests() {
|
||||
uri.parse("//example.com/#%E5%90%88%E6%B0%97%E9%81%93")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("example.com"),
|
||||
path: "/",
|
||||
fragment: Some("%E5%90%88%E6%B0%97%E9%81%93"),
|
||||
@@ -543,15 +556,17 @@ fn parse_special_tests() {
|
||||
describe("special parsing", [
|
||||
it("special 1", fn() {
|
||||
uri.parse("//?")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some(""), query: Some(""))))
|
||||
|> should.equal(Ok(
|
||||
Uri(..types.empty_uri, host: Some(""), query: Some("")),
|
||||
))
|
||||
uri.parse("//#")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some(""), fragment: Some("")),
|
||||
Uri(..types.empty_uri, host: Some(""), fragment: Some("")),
|
||||
))
|
||||
uri.parse("//?#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some(""),
|
||||
query: Some(""),
|
||||
fragment: Some(""),
|
||||
@@ -560,7 +575,7 @@ fn parse_special_tests() {
|
||||
uri.parse("foo://?")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some(""),
|
||||
query: Some(""),
|
||||
@@ -569,7 +584,7 @@ fn parse_special_tests() {
|
||||
uri.parse("foo://#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some(""),
|
||||
fragment: Some(""),
|
||||
@@ -578,7 +593,7 @@ fn parse_special_tests() {
|
||||
uri.parse("foo://?#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some(""),
|
||||
query: Some(""),
|
||||
@@ -586,23 +601,23 @@ fn parse_special_tests() {
|
||||
),
|
||||
))
|
||||
uri.parse("///")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some(""), path: "/")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, host: Some(""), path: "/")))
|
||||
uri.parse("///hostname")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some(""), path: "/hostname"),
|
||||
Uri(..types.empty_uri, host: Some(""), path: "/hostname"),
|
||||
))
|
||||
uri.parse("///?")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some(""), path: "/", query: Some("")),
|
||||
Uri(..types.empty_uri, host: Some(""), path: "/", query: Some("")),
|
||||
))
|
||||
uri.parse("///#")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some(""), path: "/", fragment: Some("")),
|
||||
Uri(..types.empty_uri, host: Some(""), path: "/", fragment: Some("")),
|
||||
))
|
||||
uri.parse("///?#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some(""),
|
||||
path: "/",
|
||||
query: Some(""),
|
||||
@@ -611,27 +626,27 @@ fn parse_special_tests() {
|
||||
))
|
||||
uri.parse("//foo?")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("foo"), query: Some("")),
|
||||
Uri(..types.empty_uri, host: Some("foo"), query: Some("")),
|
||||
))
|
||||
uri.parse("//foo#")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("foo"), fragment: Some("")),
|
||||
Uri(..types.empty_uri, host: Some("foo"), fragment: Some("")),
|
||||
))
|
||||
uri.parse("//foo?#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
host: Some("foo"),
|
||||
query: Some(""),
|
||||
fragment: Some(""),
|
||||
),
|
||||
))
|
||||
uri.parse("//foo/")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, host: Some("foo"), path: "/")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, host: Some("foo"), path: "/")))
|
||||
uri.parse("http://foo?")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("http"),
|
||||
host: Some("foo"),
|
||||
query: Some(""),
|
||||
@@ -640,7 +655,7 @@ fn parse_special_tests() {
|
||||
uri.parse("http://foo#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("http"),
|
||||
host: Some("foo"),
|
||||
fragment: Some(""),
|
||||
@@ -649,7 +664,7 @@ fn parse_special_tests() {
|
||||
uri.parse("http://foo?#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("http"),
|
||||
host: Some("foo"),
|
||||
query: Some(""),
|
||||
@@ -658,12 +673,17 @@ fn parse_special_tests() {
|
||||
))
|
||||
uri.parse("http://foo/")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, scheme: Some("http"), host: Some("foo"), path: "/"),
|
||||
Uri(
|
||||
..types.empty_uri,
|
||||
scheme: Some("http"),
|
||||
host: Some("foo"),
|
||||
path: "/",
|
||||
),
|
||||
))
|
||||
uri.parse("http://foo:80?")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("http"),
|
||||
host: Some("foo"),
|
||||
port: Some(80),
|
||||
@@ -673,7 +693,7 @@ fn parse_special_tests() {
|
||||
uri.parse("http://foo:80#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("http"),
|
||||
host: Some("foo"),
|
||||
port: Some(80),
|
||||
@@ -683,7 +703,7 @@ fn parse_special_tests() {
|
||||
uri.parse("http://foo:80?#")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("http"),
|
||||
host: Some("foo"),
|
||||
port: Some(80),
|
||||
@@ -694,7 +714,7 @@ fn parse_special_tests() {
|
||||
uri.parse("http://foo:80/")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("http"),
|
||||
host: Some("foo"),
|
||||
port: Some(80),
|
||||
@@ -702,23 +722,23 @@ fn parse_special_tests() {
|
||||
),
|
||||
))
|
||||
uri.parse("?")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "", query: Some(""))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "", query: Some(""))))
|
||||
uri.parse("??")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "", query: Some("?"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "", query: Some("?"))))
|
||||
uri.parse("???")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "", query: Some("??"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "", query: Some("??"))))
|
||||
uri.parse("#")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "", fragment: Some(""))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "", fragment: Some(""))))
|
||||
uri.parse("##")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "", fragment: Some("#"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "", fragment: Some("#"))))
|
||||
uri.parse("###")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, path: "", fragment: Some("##"))))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, path: "", fragment: Some("##"))))
|
||||
}),
|
||||
it("special 2", fn() {
|
||||
uri.parse("a://:1/")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("a"),
|
||||
host: Some(""),
|
||||
port: Some(1),
|
||||
@@ -726,15 +746,15 @@ fn parse_special_tests() {
|
||||
),
|
||||
))
|
||||
uri.parse("a:/a/")
|
||||
|> should.equal(Ok(Uri(..uri.empty_uri, scheme: Some("a"), path: "/a/")))
|
||||
|> should.equal(Ok(Uri(..types.empty_uri, scheme: Some("a"), path: "/a/")))
|
||||
uri.parse("//@")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some(""), path: "", userinfo: Some("")),
|
||||
Uri(..types.empty_uri, host: Some(""), path: "", userinfo: Some("")),
|
||||
))
|
||||
uri.parse("foo://@")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some(""),
|
||||
path: "",
|
||||
@@ -743,12 +763,12 @@ fn parse_special_tests() {
|
||||
))
|
||||
uri.parse("//@/")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some(""), path: "/", userinfo: Some("")),
|
||||
Uri(..types.empty_uri, host: Some(""), path: "/", userinfo: Some("")),
|
||||
))
|
||||
uri.parse("foo://@/")
|
||||
|> should.equal(Ok(
|
||||
Uri(
|
||||
..uri.empty_uri,
|
||||
..types.empty_uri,
|
||||
scheme: Some("foo"),
|
||||
host: Some(""),
|
||||
path: "/",
|
||||
@@ -757,11 +777,11 @@ fn parse_special_tests() {
|
||||
))
|
||||
uri.parse("//localhost:/")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("localhost"), path: "/"),
|
||||
Uri(..types.empty_uri, host: Some("localhost"), path: "/"),
|
||||
))
|
||||
uri.parse("//:")
|
||||
|> should.equal(Ok(
|
||||
Uri(..uri.empty_uri, host: Some("localhost"), path: ""),
|
||||
Uri(..types.empty_uri, host: Some("localhost"), path: ""),
|
||||
))
|
||||
}),
|
||||
])
|
||||
@@ -777,6 +797,8 @@ pub fn parse_failure_tests() {
|
||||
uri.parse("//host/path#foö") |> should.be_error
|
||||
uri.parse("//[:::127.0.0.1]") |> should.be_error
|
||||
uri.parse("//localhost:A8") |> should.be_error
|
||||
uri.parse("http://f%ff%%ff/") |> should.be_error
|
||||
uri.parse("http://f%ff%fr/") |> should.be_error
|
||||
}),
|
||||
])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user