Skip to content

Commit 0d31501

Browse files
jechollpil
authored andcommitted
Refactor uri.gleam
1 parent e2587fe commit 0d31501

File tree

1 file changed

+39
-75
lines changed

1 file changed

+39
-75
lines changed

src/gleam/uri.gleam

Lines changed: 39 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ type UriKey {
4343
Fragment
4444
}
4545

46-
/// Parses a complient URI string into the `Uri` Type.
46+
/// Parses a compliant URI string into the `Uri` Type.
4747
/// If the string is not a valid URI string then an error is returned.
4848
///
4949
/// The opposite operation is `uri.to_string`
@@ -117,7 +117,10 @@ pub fn query_to_string(query: List(tuple(String, String))) -> String {
117117
|> result.unwrap("")
118118
}
119119

120-
fn do_remove_dot_segments(input, accumulator) {
120+
fn do_remove_dot_segments(
121+
input: List(String),
122+
accumulator: List(String),
123+
) -> List(String) {
121124
case input {
122125
[] -> list.reverse(accumulator)
123126
[segment, ..rest] -> {
@@ -133,7 +136,7 @@ fn do_remove_dot_segments(input, accumulator) {
133136
}
134137
}
135138

136-
fn remove_dot_segments(input) {
139+
fn remove_dot_segments(input: List(String)) -> List(String) {
137140
do_remove_dot_segments(input, [])
138141
}
139142

@@ -142,7 +145,7 @@ fn remove_dot_segments(input) {
142145
/// Removes empty segments and resolves dot-segments as specified in
143146
/// [section 5.2](https://www.ietf.org/rfc/rfc3986.html#section-5.2) of the RFC.
144147
///
145-
pub fn path_segments(path) {
148+
pub fn path_segments(path: String) -> List(String) {
146149
remove_dot_segments(string.split(path, "/"))
147150
}
148151

@@ -154,10 +157,14 @@ external fn erl_to_string(Map(UriKey, Dynamic)) -> Dynamic =
154157
/// The opposite operation is `uri.parse`.
155158
///
156159
pub fn to_string(uri: Uri) -> String {
157-
let field = fn(key: UriKey, value: Option(anything)) {
158-
value
159-
|> option.to_result(Nil)
160-
|> result.map(fn(value) { tuple(key, dynamic.from(value)) })
160+
let field = fn(
161+
key: UriKey,
162+
value: Option(anything),
163+
) -> Result(tuple(UriKey, Dynamic), Nil) {
164+
case value {
165+
Some(v) -> Ok(tuple(key, dynamic.from(v)))
166+
None -> Error(Nil)
167+
}
161168
}
162169

163170
[
@@ -194,16 +201,12 @@ pub fn origin(uri: Uri) -> Result(String, Nil) {
194201
}
195202
}
196203

197-
fn drop_last(elements) {
198-
let tuple(keep, _last) = list.split(elements, list.length(elements) - 1)
199-
keep
204+
fn drop_last(elements: List(a)) -> List(a) {
205+
list.take(from: elements, up_to: list.length(elements) - 1)
200206
}
201207

202-
fn join_segments(segments) {
203-
case segments {
204-
[] -> ""
205-
_ -> string.append("/", string.join(segments, "/"))
206-
}
208+
fn join_segments(segments: List(String)) -> String {
209+
string.join(["", ..segments], "/")
207210
}
208211

209212
/// Resolve a uri with respect to the given base uri
@@ -213,27 +216,12 @@ fn join_segments(segments) {
213216
pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) {
214217
case base {
215218
Uri(scheme: Some(_), host: Some(_), ..) -> case relative {
216-
Uri(scheme: Some(_), ..) -> {
217-
let path = string.split(relative.path, "/")
218-
|> remove_dot_segments()
219-
|> join_segments()
220-
let resolved = Uri(
221-
relative.scheme,
222-
None,
223-
relative.host,
224-
relative.port,
225-
path,
226-
relative.query,
227-
relative.fragment,
228-
)
229-
Ok(resolved)
230-
}
231-
Uri(scheme: None, host: Some(_), ..) -> {
219+
Uri(host: Some(_), ..) -> {
232220
let path = string.split(relative.path, "/")
233221
|> remove_dot_segments()
234222
|> join_segments()
235223
let resolved = Uri(
236-
base.scheme,
224+
option.or(relative.scheme, base.scheme),
237225
None,
238226
relative.host,
239227
relative.port,
@@ -243,57 +231,33 @@ pub fn merge(base: Uri, relative: Uri) -> Result(Uri, Nil) {
243231
)
244232
Ok(resolved)
245233
}
246-
Uri(scheme: None, host: None, path: "", ..) -> {
234+
Uri(scheme: None, host: None, ..) -> {
235+
let tuple(new_path, new_query) = case relative.path {
236+
"" -> tuple(base.path, option.or(relative.query, base.query))
237+
_ -> {
238+
let path_segments = case string.starts_with(relative.path, "/") {
239+
True -> string.split(relative.path, "/")
240+
False -> string.split(base.path, "/")
241+
|> drop_last()
242+
|> list.append(string.split(relative.path, "/"))
243+
}
244+
let path = path_segments
245+
|> remove_dot_segments()
246+
|> join_segments()
247+
tuple(path, relative.query)
248+
}
249+
}
247250
let resolved = Uri(
248251
base.scheme,
249252
None,
250253
base.host,
251254
base.port,
252-
base.path,
253-
option.or(relative.query, base.query),
255+
new_path,
256+
new_query,
254257
relative.fragment,
255258
)
256259
Ok(resolved)
257260
}
258-
Uri(
259-
scheme: None,
260-
host: None,
261-
path: path,
262-
..,
263-
) -> case string.starts_with(path, "/") {
264-
True -> {
265-
let path = string.split(relative.path, "/")
266-
|> remove_dot_segments()
267-
|> join_segments()
268-
let resolved = Uri(
269-
base.scheme,
270-
None,
271-
base.host,
272-
base.port,
273-
path,
274-
relative.query,
275-
relative.fragment,
276-
)
277-
Ok(resolved)
278-
}
279-
False -> {
280-
let path = string.split(base.path, "/")
281-
|> drop_last()
282-
|> list.append(string.split(relative.path, "/"))
283-
|> remove_dot_segments()
284-
|> join_segments()
285-
let resolved = Uri(
286-
base.scheme,
287-
None,
288-
base.host,
289-
base.port,
290-
path,
291-
relative.query,
292-
relative.fragment,
293-
)
294-
Ok(resolved)
295-
}
296-
}
297261
}
298262
_ -> Error(Nil)
299263
}

0 commit comments

Comments
 (0)