diff --git a/lib/elixir/lib/base.ex b/lib/elixir/lib/base.ex index 3deaccdc2d4..d2e3da7ca77 100644 --- a/lib/elixir/lib/base.ex +++ b/lib/elixir/lib/base.ex @@ -1268,14 +1268,10 @@ defmodule Base do pad? = Keyword.get(opts, :padding, true) case Keyword.get(opts, :case, :upper) do - :upper -> validate32upper!(string, pad?) - :lower -> validate32lower!(string, pad?) - :mixed -> validate32mixed!(string, pad?) + :upper -> validate32upper?(string, pad?) + :lower -> validate32lower?(string, pad?) + :mixed -> validate32mixed?(string, pad?) end - - true - rescue - ArgumentError -> false end @doc """ @@ -1406,14 +1402,10 @@ defmodule Base do pad? = Keyword.get(opts, :padding, true) case Keyword.get(opts, :case, :upper) do - :upper -> validate32hexupper!(string, pad?) - :lower -> validate32hexlower!(string, pad?) - :mixed -> validate32hexmixed!(string, pad?) + :upper -> validate32hexupper?(string, pad?) + :lower -> validate32hexlower?(string, pad?) + :mixed -> validate32hexmixed?(string, pad?) end - - true - rescue - ArgumentError -> false end upper = Enum.with_index(b32_alphabet) @@ -1428,96 +1420,112 @@ defmodule Base do hexmixed: to_mixed_dec.(hexupper) ] do decode_name = :"decode32#{base}!" - validate_name = :"validate32#{base}!" + validate_name = :"validate32#{base}?" + validate_main_name = :"validate_main32#{validate_name}?" + valid_char_name = :"valid_char32#{base}?" {min, decoded} = to_decode_list.(alphabet) - defp unquote(validate_name)(<<>>, _pad?) do - :ok + defp unquote(validate_main_name)(<<>>), do: true + + defp unquote(validate_main_name)( + <> + ) do + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) and + unquote(valid_char_name)(c3) and + unquote(valid_char_name)(c4) and + unquote(valid_char_name)(c5) and + unquote(valid_char_name)(c6) and + unquote(valid_char_name)(c7) and + unquote(valid_char_name)(c8) and + unquote(validate_main_name)(rest) end + defp unquote(validate_name)(<<>>, _pad?), do: true + defp unquote(validate_name)(string, pad?) do segs = div(byte_size(string) + 7, 8) - 1 <> = string - - for <> do - unquote(decode_name)(c1) - unquote(decode_name)(c2) - unquote(decode_name)(c3) - unquote(decode_name)(c4) - unquote(decode_name)(c5) - unquote(decode_name)(c6) - unquote(decode_name)(c7) - unquote(decode_name)(c8) - end + main_valid? = unquote(validate_main_name)(main) case rest do + _ when not main_valid? -> + false + <> -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) <> -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) - unquote(decode_name)(c3) - unquote(decode_name)(c4) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) and + unquote(valid_char_name)(c3) and + unquote(valid_char_name)(c4) <> -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) - unquote(decode_name)(c3) - unquote(decode_name)(c4) - unquote(decode_name)(c5) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) and + unquote(valid_char_name)(c3) and + unquote(valid_char_name)(c4) and + unquote(valid_char_name)(c5) <> -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) - unquote(decode_name)(c3) - unquote(decode_name)(c4) - unquote(decode_name)(c5) - unquote(decode_name)(c6) - unquote(decode_name)(c7) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) and + unquote(valid_char_name)(c3) and + unquote(valid_char_name)(c4) and + unquote(valid_char_name)(c5) and + unquote(valid_char_name)(c6) and + unquote(valid_char_name)(c7) <> -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) - unquote(decode_name)(c3) - unquote(decode_name)(c4) - unquote(decode_name)(c5) - unquote(decode_name)(c6) - unquote(decode_name)(c7) - unquote(decode_name)(c8) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) and + unquote(valid_char_name)(c3) and + unquote(valid_char_name)(c4) and + unquote(valid_char_name)(c5) and + unquote(valid_char_name)(c6) and + unquote(valid_char_name)(c7) and + unquote(valid_char_name)(c8) <> when not pad? -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) <> when not pad? -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) - unquote(decode_name)(c3) - unquote(decode_name)(c4) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) and + unquote(valid_char_name)(c3) and + unquote(valid_char_name)(c4) <> when not pad? -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) - unquote(decode_name)(c3) - unquote(decode_name)(c4) - unquote(decode_name)(c5) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) and + unquote(valid_char_name)(c3) and + unquote(valid_char_name)(c4) and + unquote(valid_char_name)(c5) <> when not pad? -> - unquote(decode_name)(c1) - unquote(decode_name)(c2) - unquote(decode_name)(c3) - unquote(decode_name)(c4) - unquote(decode_name)(c5) - unquote(decode_name)(c6) - unquote(decode_name)(c7) + unquote(valid_char_name)(c1) and + unquote(valid_char_name)(c2) and + unquote(valid_char_name)(c3) and + unquote(valid_char_name)(c4) and + unquote(valid_char_name)(c5) and + unquote(valid_char_name)(c6) and + unquote(valid_char_name)(c7) _ -> - raise ArgumentError, "incorrect padding" + false end end + @compile {:inline, [{valid_char_name, 1}]} + defp unquote(valid_char_name)(char) + when elem({unquote_splicing(decoded)}, char - unquote(min)) != nil, + do: true + + defp unquote(valid_char_name)(_char), do: false + defp unquote(decode_name)(char) do index = char - unquote(min)