summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParker Selbert <parker@sorentwo.com>2021-12-05 12:50:22 -0600
committerGitHub <noreply@github.com>2021-12-05 19:50:22 +0100
commit1f0422ac2ede9b13aee6e6b1674616e140b2945e (patch)
tree1c557aa421c7a80988cf26eaed4ea869e5f13b26
parent5b1b85be84b44dd9a949aeaba1f86805a69bb7c0 (diff)
downloadelixir-1f0422ac2ede9b13aee6e6b1674616e140b2945e.tar.gz
Specific base typespecs (#11449)
* Use specific options for base option typespecs Each function had `keyword` as the option type, which didn't help guard against typos or mismatched options. * Fix padding use in encode/decode identity test
-rw-r--r--lib/elixir/lib/base.ex33
-rw-r--r--lib/elixir/test/elixir/base_test.exs15
2 files changed, 31 insertions, 17 deletions
diff --git a/lib/elixir/lib/base.ex b/lib/elixir/lib/base.ex
index 2eb2265d4..c902963b6 100644
--- a/lib/elixir/lib/base.ex
+++ b/lib/elixir/lib/base.ex
@@ -92,6 +92,9 @@ defmodule Base do
"""
+ @type encode_case :: :upper | :lower
+ @type decode_case :: :upper | :lower | :mixed
+
b16_alphabet = '0123456789ABCDEF'
b64_alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
b64url_alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'
@@ -267,7 +270,7 @@ defmodule Base do
"666f6f626172"
"""
- @spec encode16(binary, keyword) :: binary
+ @spec encode16(binary, case: encode_case) :: binary
def encode16(data, opts \\ []) when is_binary(data) do
case = Keyword.get(opts, :case, :upper)
do_encode16(case, data)
@@ -300,7 +303,7 @@ defmodule Base do
{:ok, "foobar"}
"""
- @spec decode16(binary, keyword) :: {:ok, binary} | :error
+ @spec decode16(binary, case: decode_case) :: {:ok, binary} | :error
def decode16(string, opts \\ []) do
{:ok, decode16!(string, opts)}
rescue
@@ -337,7 +340,7 @@ defmodule Base do
"foobar"
"""
- @spec decode16!(binary, keyword) :: binary
+ @spec decode16!(binary, case: encode_case) :: binary
def decode16!(string, opts \\ [])
def decode16!(string, opts) when is_binary(string) and rem(byte_size(string), 2) == 0 do
@@ -367,7 +370,7 @@ defmodule Base do
"Zm9vYg"
"""
- @spec encode64(binary, keyword) :: binary
+ @spec encode64(binary, padding: boolean) :: binary
def encode64(data, opts \\ []) when is_binary(data) do
pad? = Keyword.get(opts, :padding, true)
do_encode64(data, pad?)
@@ -397,7 +400,7 @@ defmodule Base do
{:ok, "foob"}
"""
- @spec decode64(binary, keyword) :: {:ok, binary} | :error
+ @spec decode64(binary, ignore: :whitespace, padding: boolean) :: {:ok, binary} | :error
def decode64(string, opts \\ []) when is_binary(string) do
{:ok, decode64!(string, opts)}
rescue
@@ -431,7 +434,7 @@ defmodule Base do
"foob"
"""
- @spec decode64!(binary, keyword) :: binary
+ @spec decode64!(binary, ignore: :whitespace, padding: boolean) :: binary
def decode64!(string, opts \\ []) when is_binary(string) do
pad? = Keyword.get(opts, :padding, true)
string |> remove_ignored(opts[:ignore]) |> do_decode64(pad?)
@@ -453,7 +456,7 @@ defmodule Base do
"_3_-_A"
"""
- @spec url_encode64(binary, keyword) :: binary
+ @spec url_encode64(binary, padding: boolean) :: binary
def url_encode64(data, opts \\ []) when is_binary(data) do
pad? = Keyword.get(opts, :padding, true)
do_encode64url(data, pad?)
@@ -481,7 +484,7 @@ defmodule Base do
{:ok, <<255, 127, 254, 252>>}
"""
- @spec url_decode64(binary, keyword) :: {:ok, binary} | :error
+ @spec url_decode64(binary, ignore: :whitespace, padding: boolean) :: {:ok, binary} | :error
def url_decode64(string, opts \\ []) when is_binary(string) do
{:ok, url_decode64!(string, opts)}
rescue
@@ -513,7 +516,7 @@ defmodule Base do
<<255, 127, 254, 252>>
"""
- @spec url_decode64!(binary, keyword) :: binary
+ @spec url_decode64!(binary, ignore: :whitespace, padding: boolean) :: binary
def url_decode64!(string, opts \\ []) when is_binary(string) do
pad? = Keyword.get(opts, :padding, true)
string |> remove_ignored(opts[:ignore]) |> do_decode64url(pad?)
@@ -551,7 +554,7 @@ defmodule Base do
"MZXW6YTBOI"
"""
- @spec encode32(binary, keyword) :: binary
+ @spec encode32(binary, case: encode_case, padding: boolean) :: binary
def encode32(data, opts \\ []) when is_binary(data) do
case = Keyword.get(opts, :case, :upper)
pad? = Keyword.get(opts, :padding, true)
@@ -594,7 +597,7 @@ defmodule Base do
{:ok, "foobar"}
"""
- @spec decode32(binary, keyword) :: {:ok, binary} | :error
+ @spec decode32(binary, case: decode_case, padding: boolean) :: {:ok, binary} | :error
def decode32(string, opts \\ []) do
{:ok, decode32!(string, opts)}
rescue
@@ -640,7 +643,7 @@ defmodule Base do
"foobar"
"""
- @spec decode32!(binary, keyword) :: binary
+ @spec decode32!(binary, case: decode_case, padding: boolean) :: binary
def decode32!(string, opts \\ []) when is_binary(string) do
case = Keyword.get(opts, :case, :upper)
pad? = Keyword.get(opts, :padding, true)
@@ -680,7 +683,7 @@ defmodule Base do
"CPNMUOJ1E8"
"""
- @spec hex_encode32(binary, keyword) :: binary
+ @spec hex_encode32(binary, case: encode_case, padding: boolean) :: binary
def hex_encode32(data, opts \\ []) when is_binary(data) do
case = Keyword.get(opts, :case, :upper)
pad? = Keyword.get(opts, :padding, true)
@@ -724,7 +727,7 @@ defmodule Base do
{:ok, "foobar"}
"""
- @spec hex_decode32(binary, keyword) :: {:ok, binary} | :error
+ @spec hex_decode32(binary, case: decode_case, padding: boolean) :: {:ok, binary} | :error
def hex_decode32(string, opts \\ []) do
{:ok, hex_decode32!(string, opts)}
rescue
@@ -771,7 +774,7 @@ defmodule Base do
"foobar"
"""
- @spec hex_decode32!(binary, keyword) :: binary
+ @spec hex_decode32!(binary, case: decode_case, padding: boolean) :: binary
def hex_decode32!(string, opts \\ []) when is_binary(string) do
case = Keyword.get(opts, :case, :upper)
pad? = Keyword.get(opts, :padding, true)
diff --git a/lib/elixir/test/elixir/base_test.exs b/lib/elixir/test/elixir/base_test.exs
index 78cc6b5ad..028a47abe 100644
--- a/lib/elixir/test/elixir/base_test.exs
+++ b/lib/elixir/test/elixir/base_test.exs
@@ -799,10 +799,21 @@ defmodule BaseTest do
|> Enum.shuffle()
|> IO.iodata_to_binary()
+ allowed_opts =
+ encode
+ |> Function.info()
+ |> Keyword.fetch!(:name)
+ |> case do
+ :encode16 -> [:case]
+ :encode64 -> [:padding]
+ :url_encode64 -> [:padding]
+ _ -> [:case, :padding]
+ end
+
expected =
data
- |> encode.(case: encode_case, pad: pad?)
- |> decode.(case: decode_case, pad: pad?)
+ |> encode.(Keyword.take([case: encode_case, padding: pad?], allowed_opts))
+ |> decode.(Keyword.take([case: decode_case, padding: pad?], allowed_opts))
assert data == expected,
"identity did not match for #{inspect(data)} when #{inspect(encode)} (#{encode_case})"