Skip to content

Commit 7c9e350

Browse files
authored
Optimize valid64? and url_valid64? (#14434)
1 parent d4f3445 commit 7c9e350

File tree

1 file changed

+82
-71
lines changed

1 file changed

+82
-71
lines changed

Diff for: lib/elixir/lib/base.ex

+82-71
Original file line numberDiff line numberDiff line change
@@ -658,10 +658,7 @@ defmodule Base do
658658
@spec valid64?(binary, ignore: :whitespace, padding: boolean) :: boolean
659659
def valid64?(string, opts \\ []) when is_binary(string) do
660660
pad? = Keyword.get(opts, :padding, true)
661-
string |> remove_ignored(opts[:ignore]) |> validate64base!(pad?)
662-
true
663-
rescue
664-
ArgumentError -> false
661+
string |> remove_ignored(opts[:ignore]) |> validate64base?(pad?)
665662
end
666663

667664
@doc """
@@ -755,110 +752,124 @@ defmodule Base do
755752
@spec url_valid64?(binary, ignore: :whitespace, padding: boolean) :: boolean
756753
def url_valid64?(string, opts \\ []) when is_binary(string) do
757754
pad? = Keyword.get(opts, :padding, true)
758-
string |> remove_ignored(opts[:ignore]) |> validate64url!(pad?)
759-
true
760-
rescue
761-
ArgumentError -> false
755+
string |> remove_ignored(opts[:ignore]) |> validate64url?(pad?)
762756
end
763757

764758
for {base, alphabet} <- [base: b64_alphabet, url: b64url_alphabet] do
765759
decode_name = :"decode64#{base}!"
766-
validate_name = :"validate64#{base}!"
760+
761+
validate_name = :"validate64#{base}?"
762+
validate_main_name = :"validate_main64#{validate_name}?"
763+
valid_char_name = :"valid_char64#{base}?"
767764
{min, decoded} = alphabet |> Enum.with_index() |> to_decode_list.()
768765

769-
defp unquote(validate_name)(<<>>, _pad?) do
770-
true
766+
defp unquote(validate_main_name)(<<>>), do: true
767+
768+
defp unquote(validate_main_name)(
769+
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, c8::8, rest::binary>>
770+
) do
771+
unquote(valid_char_name)(c1) and
772+
unquote(valid_char_name)(c2) and
773+
unquote(valid_char_name)(c3) and
774+
unquote(valid_char_name)(c4) and
775+
unquote(valid_char_name)(c5) and
776+
unquote(valid_char_name)(c6) and
777+
unquote(valid_char_name)(c7) and
778+
unquote(valid_char_name)(c8) and
779+
unquote(validate_main_name)(rest)
771780
end
772781

782+
defp unquote(validate_name)(<<>>, _pad?), do: true
783+
773784
defp unquote(validate_name)(string, pad?) do
774785
segs = div(byte_size(string) + 7, 8) - 1
775786
<<main::size(^segs)-binary-unit(64), rest::binary>> = string
776-
777-
for <<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, c8::8 <- main>> do
778-
unquote(decode_name)(c1)
779-
unquote(decode_name)(c2)
780-
unquote(decode_name)(c3)
781-
unquote(decode_name)(c4)
782-
unquote(decode_name)(c5)
783-
unquote(decode_name)(c6)
784-
unquote(decode_name)(c7)
785-
unquote(decode_name)(c8)
786-
end
787+
main_valid? = unquote(validate_main_name)(main)
787788

788789
case rest do
790+
_ when not main_valid? ->
791+
false
792+
789793
<<c1::8, c2::8, ?=, ?=>> ->
790-
unquote(decode_name)(c1)
791-
unquote(decode_name)(c2)
794+
unquote(valid_char_name)(c1) and
795+
unquote(valid_char_name)(c2)
792796

793797
<<c1::8, c2::8, c3::8, ?=>> ->
794-
unquote(decode_name)(c1)
795-
unquote(decode_name)(c2)
796-
unquote(decode_name)(c3)
798+
unquote(valid_char_name)(c1) and
799+
unquote(valid_char_name)(c2) and
800+
unquote(valid_char_name)(c3)
797801

798802
<<c1::8, c2::8, c3::8, c4::8>> ->
799-
unquote(decode_name)(c1)
800-
unquote(decode_name)(c2)
801-
unquote(decode_name)(c3)
802-
unquote(decode_name)(c4)
803+
unquote(valid_char_name)(c1) and
804+
unquote(valid_char_name)(c2) and
805+
unquote(valid_char_name)(c3) and
806+
unquote(valid_char_name)(c4)
803807

804808
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, ?=, ?=>> ->
805-
unquote(decode_name)(c1)
806-
unquote(decode_name)(c2)
807-
unquote(decode_name)(c3)
808-
unquote(decode_name)(c4)
809-
unquote(decode_name)(c5)
810-
unquote(decode_name)(c6)
809+
unquote(valid_char_name)(c1) and
810+
unquote(valid_char_name)(c2) and
811+
unquote(valid_char_name)(c3) and
812+
unquote(valid_char_name)(c4) and
813+
unquote(valid_char_name)(c5) and
814+
unquote(valid_char_name)(c6)
811815

812816
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, ?=>> ->
813-
unquote(decode_name)(c1)
814-
unquote(decode_name)(c2)
815-
unquote(decode_name)(c3)
816-
unquote(decode_name)(c4)
817-
unquote(decode_name)(c5)
818-
unquote(decode_name)(c6)
819-
unquote(decode_name)(c7)
817+
unquote(valid_char_name)(c1) and
818+
unquote(valid_char_name)(c2) and
819+
unquote(valid_char_name)(c3) and
820+
unquote(valid_char_name)(c4) and
821+
unquote(valid_char_name)(c5) and
822+
unquote(valid_char_name)(c6) and
823+
unquote(valid_char_name)(c7)
820824

821825
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8, c8::8>> ->
822-
unquote(decode_name)(c1)
823-
unquote(decode_name)(c2)
824-
unquote(decode_name)(c3)
825-
unquote(decode_name)(c4)
826-
unquote(decode_name)(c5)
827-
unquote(decode_name)(c6)
828-
unquote(decode_name)(c7)
829-
unquote(decode_name)(c8)
826+
unquote(valid_char_name)(c1) and
827+
unquote(valid_char_name)(c2) and
828+
unquote(valid_char_name)(c3) and
829+
unquote(valid_char_name)(c4) and
830+
unquote(valid_char_name)(c5) and
831+
unquote(valid_char_name)(c6) and
832+
unquote(valid_char_name)(c7) and
833+
unquote(valid_char_name)(c8)
830834

831835
<<c1::8, c2::8>> when not pad? ->
832-
unquote(decode_name)(c1)
833-
unquote(decode_name)(c2)
836+
unquote(valid_char_name)(c1) and
837+
unquote(valid_char_name)(c2)
834838

835839
<<c1::8, c2::8, c3::8>> when not pad? ->
836-
unquote(decode_name)(c1)
837-
unquote(decode_name)(c2)
838-
unquote(decode_name)(c3)
840+
unquote(valid_char_name)(c1) and
841+
unquote(valid_char_name)(c2) and
842+
unquote(valid_char_name)(c3)
839843

840844
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8>> when not pad? ->
841-
unquote(decode_name)(c1)
842-
unquote(decode_name)(c2)
843-
unquote(decode_name)(c3)
844-
unquote(decode_name)(c4)
845-
unquote(decode_name)(c5)
846-
unquote(decode_name)(c6)
845+
unquote(valid_char_name)(c1) and
846+
unquote(valid_char_name)(c2) and
847+
unquote(valid_char_name)(c3) and
848+
unquote(valid_char_name)(c4) and
849+
unquote(valid_char_name)(c5) and
850+
unquote(valid_char_name)(c6)
847851

848852
<<c1::8, c2::8, c3::8, c4::8, c5::8, c6::8, c7::8>> when not pad? ->
849-
unquote(decode_name)(c1)
850-
unquote(decode_name)(c2)
851-
unquote(decode_name)(c3)
852-
unquote(decode_name)(c4)
853-
unquote(decode_name)(c5)
854-
unquote(decode_name)(c6)
855-
unquote(decode_name)(c7)
853+
unquote(valid_char_name)(c1) and
854+
unquote(valid_char_name)(c2) and
855+
unquote(valid_char_name)(c3) and
856+
unquote(valid_char_name)(c4) and
857+
unquote(valid_char_name)(c5) and
858+
unquote(valid_char_name)(c6) and
859+
unquote(valid_char_name)(c7)
856860

857861
_ ->
858-
raise ArgumentError, "incorrect padding"
862+
false
859863
end
860864
end
861865

866+
@compile {:inline, [{valid_char_name, 1}]}
867+
defp unquote(valid_char_name)(char)
868+
when elem({unquote_splicing(decoded)}, char - unquote(min)) != nil,
869+
do: true
870+
871+
defp unquote(valid_char_name)(_char), do: false
872+
862873
defp unquote(decode_name)(char) do
863874
index = char - unquote(min)
864875

0 commit comments

Comments
 (0)