Skip to content

Commit c8b18a4

Browse files
committed
Refactor things here and there in the URI module (#4714)
Mainly: * renamed a bunch to make them clearer (especially one-letter variables) * renamed a couple of private functions so that their name is more expressive * added guards to some functions
1 parent 309498a commit c8b18a4

File tree

1 file changed

+83
-82
lines changed

1 file changed

+83
-82
lines changed

lib/elixir/lib/uri.ex

Lines changed: 83 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ defmodule URI do
5858
new URIs.
5959
"""
6060
@spec default_port(binary, pos_integer) :: :ok
61-
def default_port(scheme, port) when is_binary(scheme) and port > 0 do
61+
def default_port(scheme, port) when is_binary(scheme) and is_integer(port) and port > 0 do
6262
:elixir_config.put({:uri, scheme}, port)
6363
end
6464

@@ -88,7 +88,22 @@ defmodule URI do
8888
8989
"""
9090
@spec encode_query(term) :: binary
91-
def encode_query(l), do: Enum.map_join(l, "&", &pair/1)
91+
def encode_query(enumerable) do
92+
Enum.map_join(enumerable, "&", &encode_kv_pair/1)
93+
end
94+
95+
defp encode_kv_pair({key, _}) when is_list(key) do
96+
raise ArgumentError, "encode_query/1 keys cannot be lists, got: #{inspect key}"
97+
end
98+
99+
defp encode_kv_pair({_, value}) when is_list(value) do
100+
raise ArgumentError, "encode_query/1 values cannot be lists, got: #{inspect value}"
101+
end
102+
103+
defp encode_kv_pair({key, value}) do
104+
encode_www_form(Kernel.to_string(key)) <>
105+
"=" <> encode_www_form(Kernel.to_string(value))
106+
end
92107

93108
@doc """
94109
Decodes a query string into a map.
@@ -110,33 +125,37 @@ defmodule URI do
110125
111126
"""
112127
@spec decode_query(binary, map) :: map
113-
def decode_query(q, map \\ %{})
128+
def decode_query(query, map \\ %{})
114129

115-
def decode_query(q, %{__struct__: _} = dict) when is_binary(q) do
130+
def decode_query(query, %{__struct__: _} = dict) when is_binary(query) do
116131
IO.warn "URI.decode_query/2 is deprecated, please use URI.decode_query/1"
117-
decode_query_dict(q, dict)
132+
decode_query_into_dict(query, dict)
118133
end
119134

120-
def decode_query(q, map) when is_binary(q) and is_map(map) do
121-
decode_query_map(q, map)
135+
def decode_query(query, map) when is_binary(query) and is_map(map) do
136+
decode_query_into_map(query, map)
122137
end
123138

124-
def decode_query(q, dict) when is_binary(q) do
139+
def decode_query(query, dict) when is_binary(query) do
125140
IO.warn "URI.decode_query/2 is deprecated, please use URI.decode_query/1"
126-
decode_query_dict(q, dict)
141+
decode_query_into_dict(query, dict)
127142
end
128143

129-
defp decode_query_map(q, map) do
130-
case do_decode_query(q) do
131-
nil -> map
132-
{{k, v}, q} -> decode_query_map(q, Map.put(map, k, v))
144+
defp decode_query_into_map(query, map) do
145+
case decode_next_query_pair(query) do
146+
nil ->
147+
map
148+
{{key, value}, rest} ->
149+
decode_query_into_map(rest, Map.put(map, key, value))
133150
end
134151
end
135152

136-
defp decode_query_dict(q, dict) do
137-
case do_decode_query(q) do
138-
nil -> dict
139-
{{k, v}, q} -> decode_query_dict(q, Dict.put(dict, k, v))
153+
defp decode_query_into_dict(query, dict) do
154+
case decode_next_query_pair(query) do
155+
nil ->
156+
dict
157+
{{key, value}, rest} ->
158+
decode_query_into_dict(rest, Dict.put(dict, key, value))
140159
end
141160
end
142161

@@ -153,43 +172,28 @@ defmodule URI do
153172
154173
"""
155174
@spec query_decoder(binary) :: Enumerable.t
156-
def query_decoder(q) when is_binary(q) do
157-
Stream.unfold(q, &do_decode_query/1)
175+
def query_decoder(query) when is_binary(query) do
176+
Stream.unfold(query, &decode_next_query_pair/1)
158177
end
159178

160-
defp do_decode_query("") do
179+
defp decode_next_query_pair("") do
161180
nil
162181
end
163182

164-
defp do_decode_query(q) do
165-
{first, next} =
166-
case :binary.split(q, "&") do
167-
[first, rest] -> {first, rest}
168-
[first] -> {first, ""}
183+
defp decode_next_query_pair(query) do
184+
{undecoded_next_pair, rest} =
185+
case :binary.split(query, "&") do
186+
[next_pair, rest] -> {next_pair, rest}
187+
[next_pair] -> {next_pair, ""}
169188
end
170189

171-
current =
172-
case :binary.split(first, "=") do
173-
[key, value] ->
174-
{decode_www_form(key), decode_www_form(value)}
175-
[key] ->
176-
{decode_www_form(key), nil}
190+
next_pair =
191+
case :binary.split(undecoded_next_pair, "=") do
192+
[key, value] -> {decode_www_form(key), decode_www_form(value)}
193+
[key] -> {decode_www_form(key), nil}
177194
end
178195

179-
{current, next}
180-
end
181-
182-
defp pair({k, _}) when is_list(k) do
183-
raise ArgumentError, "encode_query/1 keys cannot be lists, got: #{inspect k}"
184-
end
185-
186-
defp pair({_, v}) when is_list(v) do
187-
raise ArgumentError, "encode_query/1 values cannot be lists, got: #{inspect v}"
188-
end
189-
190-
defp pair({k, v}) do
191-
encode_www_form(Kernel.to_string(k)) <>
192-
"=" <> encode_www_form(Kernel.to_string(v))
196+
{next_pair, rest}
193197
end
194198

195199
@doc """
@@ -204,9 +208,9 @@ defmodule URI do
204208
true
205209
206210
"""
207-
@spec char_reserved?(term) :: boolean
208-
def char_reserved?(c) do
209-
c in ':/?#[]@!$&\'()*+,;='
211+
@spec char_reserved?(char) :: boolean
212+
def char_reserved?(char) when char in 0..0x10ffff do
213+
char in ':/?#[]@!$&\'()*+,;='
210214
end
211215

212216
@doc """
@@ -221,12 +225,12 @@ defmodule URI do
221225
true
222226
223227
"""
224-
@spec char_unreserved?(term) :: boolean
225-
def char_unreserved?(c) do
226-
c in ?0..?9 or
227-
c in ?a..?z or
228-
c in ?A..?Z or
229-
c in '~_-.'
228+
@spec char_unreserved?(char) :: boolean
229+
def char_unreserved?(char) when char in 0..0x10ffff do
230+
char in ?0..?9 or
231+
char in ?a..?z or
232+
char in ?A..?Z or
233+
char in '~_-.'
230234
end
231235

232236
@doc """
@@ -241,9 +245,9 @@ defmodule URI do
241245
false
242246
243247
"""
244-
@spec char_unescaped?(term) :: boolean
245-
def char_unescaped?(c) do
246-
char_reserved?(c) or char_unreserved?(c)
248+
@spec char_unescaped?(char) :: boolean
249+
def char_unescaped?(char) when char in 0..0x10ffff do
250+
char_reserved?(char) or char_unreserved?(char)
247251
end
248252

249253
@doc """
@@ -264,8 +268,9 @@ defmodule URI do
264268
265269
"""
266270
@spec encode(binary, (byte -> boolean)) :: binary
267-
def encode(str, predicate \\ &char_unescaped?/1) when is_binary(str) do
268-
for <<c <- str>>, into: "", do: percent(c, predicate)
271+
def encode(string, predicate \\ &char_unescaped?/1)
272+
when is_binary(string) and is_function(predicate, 1) do
273+
for <<char <- string>>, into: "", do: percent(char, predicate)
269274
end
270275

271276
@doc """
@@ -278,20 +283,20 @@ defmodule URI do
278283
279284
"""
280285
@spec encode_www_form(binary) :: binary
281-
def encode_www_form(str) when is_binary(str) do
282-
for <<c <- str>>, into: "" do
283-
case percent(c, &char_unreserved?/1) do
286+
def encode_www_form(string) when is_binary(string) do
287+
for <<char <- string>>, into: "" do
288+
case percent(char, &char_unreserved?/1) do
284289
"%20" -> "+"
285-
pct -> pct
290+
percent -> percent
286291
end
287292
end
288293
end
289294

290-
defp percent(c, predicate) do
291-
if predicate.(c) do
292-
<<c>>
295+
defp percent(char, predicate) do
296+
if predicate.(char) do
297+
<<char>>
293298
else
294-
"%" <> hex(bsr(c, 4)) <> hex(band(c, 15))
299+
"%" <> hex(bsr(char, 4)) <> hex(band(char, 15))
295300
end
296301
end
297302

@@ -325,11 +330,11 @@ defmodule URI do
325330
326331
"""
327332
@spec decode_www_form(binary) :: binary
328-
def decode_www_form(str) do
329-
unpercent(str, "", true)
333+
def decode_www_form(string) do
334+
unpercent(string, "", true)
330335
catch
331336
:malformed_uri ->
332-
raise ArgumentError, "malformed URI #{inspect str}"
337+
raise ArgumentError, "malformed URI #{inspect string}"
333338
end
334339

335340
defp unpercent(<<?+, tail::binary>>, acc, spaces = true) do
@@ -392,15 +397,15 @@ defmodule URI do
392397

393398
def parse(%URI{} = uri), do: uri
394399

395-
def parse(s) when is_binary(s) do
400+
def parse(string) when is_binary(string) do
396401
# From http://tools.ietf.org/html/rfc3986#appendix-B
397402
regex = ~r/^(([a-z][a-z0-9\+\-\.]*):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/i
398-
parts = nillify(Regex.run(regex, s))
403+
parts = nillify(Regex.run(regex, string))
399404

400405
destructure [_, _, scheme, _, authority, path, _, query, _, fragment], parts
401406
{userinfo, host, port} = split_authority(authority)
402407

403-
scheme = normalize_scheme(scheme)
408+
scheme = scheme && String.downcase(scheme)
404409
port = port || (scheme && default_port(scheme))
405410

406411
%URI{
@@ -411,9 +416,8 @@ defmodule URI do
411416
end
412417

413418
# Split an authority into its userinfo, host and port parts.
414-
defp split_authority(s) do
415-
s = s || ""
416-
components = Regex.run ~r/(^(.*)@)?(\[[a-zA-Z0-9:.]*\]|[^:]*)(:(\d*))?/, s
419+
defp split_authority(string) do
420+
components = Regex.run(~r/(^(.*)@)?(\[[a-zA-Z0-9:.]*\]|[^:]*)(:(\d*))?/, string || "")
417421

418422
destructure [_, _, userinfo, host, _, port], nillify(components)
419423
host = if host, do: host |> String.trim_leading("[") |> String.trim_trailing("]")
@@ -422,14 +426,11 @@ defmodule URI do
422426
{userinfo, host, port}
423427
end
424428

425-
defp normalize_scheme(nil), do: nil
426-
defp normalize_scheme(scheme), do: String.downcase(scheme)
427-
428429
# Regex.run returns empty strings sometimes. We want
429430
# to replace those with nil for consistency.
430-
defp nillify(l) do
431-
for s <- l do
432-
if byte_size(s) > 0, do: s
431+
defp nillify(list) do
432+
for string <- list do
433+
if byte_size(string) > 0, do: string
433434
end
434435
end
435436

0 commit comments

Comments
 (0)