diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..6b482e0 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,27 @@ +name: ci + +on: + push: + paths-ignore: + - "doc/**" + - "**.rst" + pull_request: + +jobs: + ci: + runs-on: ubuntu-latest + container: + image: shiguredo/erlang:otp-26.0-rc3-openssl-3.1.0-ubuntu-22.04-x86_64 + env: + ERL_FLAGS: -enable-feature maybe_expr + steps: + - uses: actions/checkout@v3 + - run: make + - name: Slack Notification + if: failure() + uses: rtCamp/action-slack-notify@v2 + env: + SLACK_CHANNEL: ${{ secrets.SLACK_INTERNAL_CHANNEL }} + SLACK_COLOR: danger + SLACK_TITLE: Failure test + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }} diff --git a/.github/workflows/make-github.yml b/.github/workflows/make-github.yml deleted file mode 100644 index c07ff51..0000000 --- a/.github/workflows/make-github.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: make-github-workflow - -on: - push: - paths-ignore: - - 'doc/**' - - '**.rst' - pull_request: - -jobs: - make-github: - runs-on: ubuntu-latest - container: - image: shiguredo/erlang:otp-24.1.4-ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - run: make diff --git a/CHANGES.md b/CHANGES.md index 034270f..e97b631 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,25 @@ ## develop +## 2023.1.0 + +日付: 2023-05-02 + +- [ADD] hex_efmt と hex_elvis を追加する + - @voluntas +- [CHANGE] efmt を適用する + - @voluntas +- [CHANGE] rebar3 の minimum_otp_vsn を 26.0 にする + - @voluntas +- [UPDATE] GitHub Actions の docker の OTP を 26.0-rc3 に上げる + - @voluntas +- [ADD] slack 通知を secrets.SLACK_INTERNAL_CHANNEL に変更 + - @voluntas +- [ADD] rebar3 3.20.0 を追加する + - @voluntas +- [ADD] elvis.config を追加する + - @voluntas + ## 2021.3.0 - [CHANGE] applicaiton を base32 に戻す @@ -11,31 +30,31 @@ - [ADD] rebar3 hex plugin を追加する - [ADD] rebar3 3.17.0 を追加する - - @voluntas + - @voluntas - [CHANGE] 最小 OTP を 24.1 に上げる - - @voluntas + - @voluntas ## 2021.1 - [FIX] `base32:decode(clockwork, _)` が Crockford になっていた問題を修正する - - @shino + - @shino - [CHANGE] `base32:decode(crockford, _)` が Binary を返していたため `{ok, Binary}` に変更する - - @shino + - @shino ## 2020.2 - [CHANGE] Clockwork Base32 を実装する - - @szktty + - @szktty ## 2020.1.2 - [FIX] Crockford's Base32: エンコード後の文字列の先頭が "0" であるべき場合に "0" が抜け落ちる事象を修正する - - @szktty + - @szktty ## 2020.1.1 - [UPDATE] Crockford 版を数値計算で再実装 - - @szktty + - @szktty ## 2020.1 @@ -46,7 +65,7 @@ ## 1.1.0 - [ADD] crockford の decode を追加 - - @szktty + - @szktty ## 1.0.0 diff --git a/Makefile b/Makefile index a1d9ee9..33e6438 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ all: clean upgrade compile test dialyzer upgrade: - @./rebar3 do update, upgrade + @./rebar3 do update, upgrade --all compile: @./rebar3 xref diff --git a/README.md b/README.md index 67cc4bc..40408ad 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,13 @@ $ rebar3 shell <<"AXQQEB10D5T20WK5C5P6RY90EXQQ4TVK44">> ``` -エンコード方式の種類: +## rebar3 deps + +```erlang +{deps, [{base32, "2023.1.0", {pkg, base32_clockwork}}]}. +``` + +## エンコード方式の種類 - `rfc4648`: RFC 4648 - `crockford`: Crockford's Base32 @@ -34,8 +40,8 @@ $ rebar3 shell ## ライセンス ``` -Copyright 2020, SUZUKI Tetsuya (Original Author) -Copyright 2020, Shiguredo Inc. +Copyright 2021-2023, Shiguredo Inc. +Copyright 2021, SUZUKI Tetsuya (Original Author) Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/elvis.config b/elvis.config new file mode 100644 index 0000000..df3e4d1 --- /dev/null +++ b/elvis.config @@ -0,0 +1,47 @@ +[ + { + elvis, + [ + {config, + [#{dirs => ["src"], + filter => "*.erl", + ruleset => erl_files, + rules => [{elvis_text_style, line_length, #{limit => 120, skip_comments => whole_line}}, + %% Ranch 利用のため Transport:send/2 的なのが必要なので ... + {elvis_style, invalid_dynamic_call, disable}, + %% snake_case じゃない場合は本来 '' で囲うべき + {elvis_style, atom_naming_convention, #{regex => "^([a-z][a-zA-Z0-9_]*_?)*(_SUITE)?$", enclosed_atoms => ".*"}}, + {elvis_style, module_naming_convention, #{regex => "^([a-z][a-z0-9]*)(_[a-z0-9]+)*(_SUITE)?$"}}, + {elvis_style, variable_naming_convention, #{regex => "^(_?[A-Z][0-9a-zA-Z_]*)$"}}, + + {elvis_style, nesting_level, disable}, + {elvis_style, god_modules, disable}, + {elvis_style, state_record_and_type, disable}, + {elvis_style, no_block_expressions, disable}, + {elvis_style, export_used_types, disable}, + {elvis_style, private_data_types, disable}, + %% 要検討 + {elvis_style, no_single_clause_case, disable}, + %% 要検討 + {elvis_style, max_function_arity, disable}, + %% 要検討 + {elvis_style, operator_spaces, disable}, + %% 要検討 + {elvis_style, no_spec_with_records, disable}, + %% 要検討 + {elvis_style, dont_repeat_yourself, disable}] + }, + #{dirs => ["."], + filter => "rebar.config", + ruleset => rebar_config, + rules => [{elvis_project, protocol_for_deps}] + }, + #{dirs => ["."], + filter => "elvis.config", + ruleset => elvis_config + } + ] + } + ] + } +]. diff --git a/rebar.config b/rebar.config index 327bc0e..20fee96 100644 --- a/rebar.config +++ b/rebar.config @@ -1,16 +1,36 @@ -{minimum_otp_vsn, "24.1"}. +{minimum_otp_vsn, "26.0"}. {erl_opts, [{i, "src"}, warnings_as_errors, warn_export_all, warn_unused_import]}. -{xref_checks, [undefined_function_calls, undefined_functions, +{xref_checks, [undefined_function_calls, + undefined_functions, locals_not_used, - deprecated_function_calls, deprecated_functions]}. + deprecated_function_calls, + deprecated_functions]}. + +%% https://rebar3.org/docs/configuration/configuration/#dialyzer +{dialyzer, [{warnings, [extra_return, + missing_return, + no_unknown + %% overspecs + %% underspecs, + %% specdiffs + %% error_handling + ]}, + incremental, + {plt_apps, top_level_deps}, + %% {plt_apps, all_apps}, + {plt_location, local}, + {base_plt_location, global}]}. {cover_enabled, true}. {validate_app_modules, true}. +{project_plugins, [rebar3_efmt, rebar3_lint]}. +{elvis_output_format, colors}. + {plugins, [rebar3_hex]}. diff --git a/rebar3 b/rebar3 index d5f99c6..3e09582 100755 Binary files a/rebar3 and b/rebar3 differ diff --git a/src/base32.app.src b/src/base32.app.src index bb7f7f6..c7a3d07 100644 --- a/src/base32.app.src +++ b/src/base32.app.src @@ -1,15 +1,12 @@ {application, base32, [{description, "Clockwork Base32"}, {pkg_name, base32_clockwork}, - {vsn, "2021.3.0"}, + {vsn, "2023.1.0"}, {registered, []}, {applications, - [ - kernel, - stdlib - ]}, - {env,[]}, + [kernel, + stdlib]}, + {env, []}, {modules, []}, - {licenses, ["Apache License, Version 2.0"]}, - {links, [{"GitHub", "https://github.com/shiguredo/base32_clockwork"}]} - ]}. + {licenses, ["Apache-2.0"]}, + {links, [{"GitHub", "https://github.com/shiguredo/base32_clockwork"}]}]}. diff --git a/src/base32.erl b/src/base32.erl index 0d21fd6..4aa81bd 100644 --- a/src/base32.erl +++ b/src/base32.erl @@ -4,6 +4,7 @@ -type base32_format() :: rfc4648 | crockford | crockford_check | clockwork. + -spec encode(base32_format(), binary()) -> binary(). encode(rfc4648, Data) -> base32_rfc4648:encode(Data); @@ -14,8 +15,9 @@ encode(crockford_check, Data) -> encode(clockwork, Data) -> base32_clockwork:encode(Data). + -spec decode(base32_format(), binary()) -> - {ok, binary()} | {error, atom()}. + {ok, binary()} | {error, atom()}. decode(rfc4648, Data) -> base32_rfc4648:decode(Data); decode(crockford, Data) -> @@ -24,4 +26,3 @@ decode(crockford_check, Data) -> base32_crockford:decode_check(Data); decode(clockwork, Data) -> base32_clockwork:decode(Data). - diff --git a/src/base32_clockwork.erl b/src/base32_clockwork.erl index a98a6d5..a48c1e1 100644 --- a/src/base32_clockwork.erl +++ b/src/base32_clockwork.erl @@ -4,22 +4,25 @@ -import(base32_utils, [rev_bits_list_to_binary/1, bits_list_size/1]). + -spec encode(binary()) -> binary(). encode(Data) -> encode0(Data, []). + encode0(<<>>, Accu) -> list_to_binary(lists:reverse(Accu)); encode0(<>, Accu) -> - encode0(Next, [symbol(Bits)|Accu]); + encode0(Next, [symbol(Bits) | Accu]); encode0(<>, Accu) -> - encode0(Next, [symbol(Bits bsl 1)|Accu]); + encode0(Next, [symbol(Bits bsl 1) | Accu]); encode0(<>, Accu) -> - encode0(Next, [symbol(Bits bsl 2)|Accu]); + encode0(Next, [symbol(Bits bsl 2) | Accu]); encode0(<>, Accu) -> - encode0(Next, [symbol(Bits bsl 3)|Accu]); + encode0(Next, [symbol(Bits bsl 3) | Accu]); encode0(<>, Accu) -> - encode0(Next, [symbol(Bits bsl 4)|Accu]). + encode0(Next, [symbol(Bits bsl 4) | Accu]). + symbol(0) -> $0; symbol(1) -> $1; @@ -54,13 +57,15 @@ symbol(29) -> $X; symbol(30) -> $Y; symbol(31) -> $Z. + -spec decode(binary()) -> {ok, binary()} | {error, atom()}. decode(Data) -> decode0(Data, []). + decode0(<<>>, []) -> {ok, <<>>}; -decode0(<<>>, Accu=[Last|Prev]) -> +decode0(<<>>, Accu = [Last | Prev]) -> Size = bits_list_size(Accu), Last1 = case Size rem 8 of 0 -> @@ -70,129 +75,128 @@ decode0(<<>>, Accu=[Last|Prev]) -> <> = Last, Last2 end, - {ok, rev_bits_list_to_binary([Last1|Prev])}; + {ok, rev_bits_list_to_binary([Last1 | Prev])}; decode0(<<_:8>>, []) -> {error, invalid_size}; decode0(<<"0", Next/binary>>, Accu) -> - decode0(Next, [<<0:5>>|Accu]); + decode0(Next, [<<0:5>> | Accu]); decode0(<<"O", Next/binary>>, Accu) -> - decode0(Next, [<<0:5>>|Accu]); + decode0(Next, [<<0:5>> | Accu]); decode0(<<"o", Next/binary>>, Accu) -> - decode0(Next, [<<0:5>>|Accu]); + decode0(Next, [<<0:5>> | Accu]); decode0(<<"1", Next/binary>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"I", Next/binary>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"i", Next/binary>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"L", Next/binary>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"l", Next/binary>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"2", Next/binary>>, Accu) -> - decode0(Next, [<<2:5>>|Accu]); + decode0(Next, [<<2:5>> | Accu]); decode0(<<"3", Next/binary>>, Accu) -> - decode0(Next, [<<3:5>>|Accu]); + decode0(Next, [<<3:5>> | Accu]); decode0(<<"4", Next/binary>>, Accu) -> - decode0(Next, [<<4:5>>|Accu]); + decode0(Next, [<<4:5>> | Accu]); decode0(<<"5", Next/binary>>, Accu) -> - decode0(Next, [<<5:5>>|Accu]); + decode0(Next, [<<5:5>> | Accu]); decode0(<<"6", Next/binary>>, Accu) -> - decode0(Next, [<<6:5>>|Accu]); + decode0(Next, [<<6:5>> | Accu]); decode0(<<"7", Next/binary>>, Accu) -> - decode0(Next, [<<7:5>>|Accu]); + decode0(Next, [<<7:5>> | Accu]); decode0(<<"8", Next/binary>>, Accu) -> - decode0(Next, [<<8:5>>|Accu]); + decode0(Next, [<<8:5>> | Accu]); decode0(<<"9", Next/binary>>, Accu) -> - decode0(Next, [<<9:5>>|Accu]); + decode0(Next, [<<9:5>> | Accu]); decode0(<<"A", Next/binary>>, Accu) -> - decode0(Next, [<<10:5>>|Accu]); + decode0(Next, [<<10:5>> | Accu]); decode0(<<"a", Next/binary>>, Accu) -> - decode0(Next, [<<10:5>>|Accu]); + decode0(Next, [<<10:5>> | Accu]); decode0(<<"B", Next/binary>>, Accu) -> - decode0(Next, [<<11:5>>|Accu]); + decode0(Next, [<<11:5>> | Accu]); decode0(<<"b", Next/binary>>, Accu) -> - decode0(Next, [<<11:5>>|Accu]); + decode0(Next, [<<11:5>> | Accu]); decode0(<<"C", Next/binary>>, Accu) -> - decode0(Next, [<<12:5>>|Accu]); + decode0(Next, [<<12:5>> | Accu]); decode0(<<"c", Next/binary>>, Accu) -> - decode0(Next, [<<12:5>>|Accu]); + decode0(Next, [<<12:5>> | Accu]); decode0(<<"D", Next/binary>>, Accu) -> - decode0(Next, [<<13:5>>|Accu]); + decode0(Next, [<<13:5>> | Accu]); decode0(<<"d", Next/binary>>, Accu) -> - decode0(Next, [<<13:5>>|Accu]); + decode0(Next, [<<13:5>> | Accu]); decode0(<<"E", Next/binary>>, Accu) -> - decode0(Next, [<<14:5>>|Accu]); + decode0(Next, [<<14:5>> | Accu]); decode0(<<"e", Next/binary>>, Accu) -> - decode0(Next, [<<14:5>>|Accu]); + decode0(Next, [<<14:5>> | Accu]); decode0(<<"F", Next/binary>>, Accu) -> - decode0(Next, [<<15:5>>|Accu]); + decode0(Next, [<<15:5>> | Accu]); decode0(<<"f", Next/binary>>, Accu) -> - decode0(Next, [<<15:5>>|Accu]); + decode0(Next, [<<15:5>> | Accu]); decode0(<<"G", Next/binary>>, Accu) -> - decode0(Next, [<<16:5>>|Accu]); + decode0(Next, [<<16:5>> | Accu]); decode0(<<"g", Next/binary>>, Accu) -> - decode0(Next, [<<16:5>>|Accu]); + decode0(Next, [<<16:5>> | Accu]); decode0(<<"H", Next/binary>>, Accu) -> - decode0(Next, [<<17:5>>|Accu]); + decode0(Next, [<<17:5>> | Accu]); decode0(<<"h", Next/binary>>, Accu) -> - decode0(Next, [<<17:5>>|Accu]); + decode0(Next, [<<17:5>> | Accu]); decode0(<<"J", Next/binary>>, Accu) -> - decode0(Next, [<<18:5>>|Accu]); + decode0(Next, [<<18:5>> | Accu]); decode0(<<"j", Next/binary>>, Accu) -> - decode0(Next, [<<18:5>>|Accu]); + decode0(Next, [<<18:5>> | Accu]); decode0(<<"K", Next/binary>>, Accu) -> - decode0(Next, [<<19:5>>|Accu]); + decode0(Next, [<<19:5>> | Accu]); decode0(<<"k", Next/binary>>, Accu) -> - decode0(Next, [<<19:5>>|Accu]); + decode0(Next, [<<19:5>> | Accu]); decode0(<<"M", Next/binary>>, Accu) -> - decode0(Next, [<<20:5>>|Accu]); + decode0(Next, [<<20:5>> | Accu]); decode0(<<"m", Next/binary>>, Accu) -> - decode0(Next, [<<20:5>>|Accu]); + decode0(Next, [<<20:5>> | Accu]); decode0(<<"N", Next/binary>>, Accu) -> - decode0(Next, [<<21:5>>|Accu]); + decode0(Next, [<<21:5>> | Accu]); decode0(<<"n", Next/binary>>, Accu) -> - decode0(Next, [<<21:5>>|Accu]); + decode0(Next, [<<21:5>> | Accu]); decode0(<<"P", Next/binary>>, Accu) -> - decode0(Next, [<<22:5>>|Accu]); + decode0(Next, [<<22:5>> | Accu]); decode0(<<"p", Next/binary>>, Accu) -> - decode0(Next, [<<22:5>>|Accu]); + decode0(Next, [<<22:5>> | Accu]); decode0(<<"Q", Next/binary>>, Accu) -> - decode0(Next, [<<23:5>>|Accu]); + decode0(Next, [<<23:5>> | Accu]); decode0(<<"q", Next/binary>>, Accu) -> - decode0(Next, [<<23:5>>|Accu]); + decode0(Next, [<<23:5>> | Accu]); decode0(<<"R", Next/binary>>, Accu) -> - decode0(Next, [<<24:5>>|Accu]); + decode0(Next, [<<24:5>> | Accu]); decode0(<<"r", Next/binary>>, Accu) -> - decode0(Next, [<<24:5>>|Accu]); + decode0(Next, [<<24:5>> | Accu]); decode0(<<"S", Next/binary>>, Accu) -> - decode0(Next, [<<25:5>>|Accu]); + decode0(Next, [<<25:5>> | Accu]); decode0(<<"s", Next/binary>>, Accu) -> - decode0(Next, [<<25:5>>|Accu]); + decode0(Next, [<<25:5>> | Accu]); decode0(<<"T", Next/binary>>, Accu) -> - decode0(Next, [<<26:5>>|Accu]); + decode0(Next, [<<26:5>> | Accu]); decode0(<<"t", Next/binary>>, Accu) -> - decode0(Next, [<<26:5>>|Accu]); + decode0(Next, [<<26:5>> | Accu]); decode0(<<"V", Next/binary>>, Accu) -> - decode0(Next, [<<27:5>>|Accu]); + decode0(Next, [<<27:5>> | Accu]); decode0(<<"v", Next/binary>>, Accu) -> - decode0(Next, [<<27:5>>|Accu]); + decode0(Next, [<<27:5>> | Accu]); decode0(<<"W", Next/binary>>, Accu) -> - decode0(Next, [<<28:5>>|Accu]); + decode0(Next, [<<28:5>> | Accu]); decode0(<<"w", Next/binary>>, Accu) -> - decode0(Next, [<<28:5>>|Accu]); + decode0(Next, [<<28:5>> | Accu]); decode0(<<"X", Next/binary>>, Accu) -> - decode0(Next, [<<29:5>>|Accu]); + decode0(Next, [<<29:5>> | Accu]); decode0(<<"x", Next/binary>>, Accu) -> - decode0(Next, [<<29:5>>|Accu]); + decode0(Next, [<<29:5>> | Accu]); decode0(<<"Y", Next/binary>>, Accu) -> - decode0(Next, [<<30:5>>|Accu]); + decode0(Next, [<<30:5>> | Accu]); decode0(<<"y", Next/binary>>, Accu) -> - decode0(Next, [<<30:5>>|Accu]); + decode0(Next, [<<30:5>> | Accu]); decode0(<<"Z", Next/binary>>, Accu) -> - decode0(Next, [<<31:5>>|Accu]); + decode0(Next, [<<31:5>> | Accu]); decode0(<<"z", Next/binary>>, Accu) -> - decode0(Next, [<<31:5>>|Accu]); + decode0(Next, [<<31:5>> | Accu]); decode0(_, _) -> {error, invalid_format}. - diff --git a/src/base32_crockford.erl b/src/base32_crockford.erl index 2a37e61..edde797 100644 --- a/src/base32_crockford.erl +++ b/src/base32_crockford.erl @@ -4,9 +4,11 @@ -import(base32_utils, [rev_bits_list_to_binary/1]). + data_to_integer(Data, Padding) -> data_to_integer0(Data, Padding, 0). + data_to_integer0(<<>>, _, N) -> N; data_to_integer0(<>, true, N) -> @@ -28,11 +30,13 @@ data_to_integer0(<>, false, N) -> data_to_integer0(<>, Padding, N) -> data_to_integer0(Next, Padding, (N bsl 5) bor Bits). + -spec encode(binary() | integer()) -> binary(). encode(Value) -> Encoded = encode0(Value, []), list_to_binary(Encoded). + -spec encode_check(binary()) -> binary(). encode_check(Data) when is_binary(Data) -> Check = check_symbol(data_to_integer(Data, false)), @@ -43,6 +47,7 @@ encode_check(Value) -> Encoded = encode0(Value, [Check]), list_to_binary(Encoded). + encode0(Data, Accu) when is_binary(Data) -> Size = size(Data) * 8, BaseCount = Size div 5, @@ -59,16 +64,19 @@ encode0(Value, Accu) -> end, encode1(Value, Count, Accu). + encode1(_, 0, Accu) -> Accu; encode1(Value, Count, Accu) -> Next = Value div 32, SymVal = Value rem 32, - encode1(Next, Count - 1, [symbol(SymVal)|Accu]). + encode1(Next, Count - 1, [symbol(SymVal) | Accu]). + check_symbol(Value) -> symbol(Value rem 37). + symbol(0) -> $0; symbol(1) -> $1; symbol(2) -> $2; @@ -107,10 +115,12 @@ symbol(34) -> $$; symbol(35) -> $=; symbol(36) -> $U. + -spec decode(binary()) -> binary(). decode(Data) when is_binary(Data) -> decode0(Data, []). + -spec decode_check(binary()) -> {ok, binary()} | {error, atom()}. decode_check(Data) -> Size = (size(Data) - 1) * 8, @@ -122,6 +132,7 @@ decode_check(Data) -> false -> {error, invalid} end. + decode0(<<>>, Accu) -> Decoded0 = rev_bits_list_to_binary(Accu), DecodedSize = bit_size(Decoded0), @@ -134,125 +145,124 @@ decode0(<<>>, Accu) -> Decoded1 end; decode0(<<"0", Next/bitstring>>, Accu) -> - decode0(Next, [<<0:5>>|Accu]); + decode0(Next, [<<0:5>> | Accu]); decode0(<<"O", Next/bitstring>>, Accu) -> - decode0(Next, [<<0:5>>|Accu]); + decode0(Next, [<<0:5>> | Accu]); decode0(<<"o", Next/bitstring>>, Accu) -> - decode0(Next, [<<0:5>>|Accu]); + decode0(Next, [<<0:5>> | Accu]); decode0(<<"1", Next/bitstring>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"I", Next/bitstring>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"i", Next/bitstring>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"L", Next/bitstring>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"l", Next/bitstring>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"2", Next/bitstring>>, Accu) -> - decode0(Next, [<<2:5>>|Accu]); + decode0(Next, [<<2:5>> | Accu]); decode0(<<"3", Next/bitstring>>, Accu) -> - decode0(Next, [<<3:5>>|Accu]); + decode0(Next, [<<3:5>> | Accu]); decode0(<<"4", Next/bitstring>>, Accu) -> - decode0(Next, [<<4:5>>|Accu]); + decode0(Next, [<<4:5>> | Accu]); decode0(<<"5", Next/bitstring>>, Accu) -> - decode0(Next, [<<5:5>>|Accu]); + decode0(Next, [<<5:5>> | Accu]); decode0(<<"6", Next/bitstring>>, Accu) -> - decode0(Next, [<<6:5>>|Accu]); + decode0(Next, [<<6:5>> | Accu]); decode0(<<"7", Next/bitstring>>, Accu) -> - decode0(Next, [<<7:5>>|Accu]); + decode0(Next, [<<7:5>> | Accu]); decode0(<<"8", Next/bitstring>>, Accu) -> - decode0(Next, [<<8:5>>|Accu]); + decode0(Next, [<<8:5>> | Accu]); decode0(<<"9", Next/bitstring>>, Accu) -> - decode0(Next, [<<9:5>>|Accu]); + decode0(Next, [<<9:5>> | Accu]); decode0(<<"A", Next/bitstring>>, Accu) -> - decode0(Next, [<<10:5>>|Accu]); + decode0(Next, [<<10:5>> | Accu]); decode0(<<"a", Next/bitstring>>, Accu) -> - decode0(Next, [<<10:5>>|Accu]); + decode0(Next, [<<10:5>> | Accu]); decode0(<<"B", Next/bitstring>>, Accu) -> - decode0(Next, [<<11:5>>|Accu]); + decode0(Next, [<<11:5>> | Accu]); decode0(<<"b", Next/bitstring>>, Accu) -> - decode0(Next, [<<11:5>>|Accu]); + decode0(Next, [<<11:5>> | Accu]); decode0(<<"C", Next/bitstring>>, Accu) -> - decode0(Next, [<<12:5>>|Accu]); + decode0(Next, [<<12:5>> | Accu]); decode0(<<"c", Next/bitstring>>, Accu) -> - decode0(Next, [<<12:5>>|Accu]); + decode0(Next, [<<12:5>> | Accu]); decode0(<<"D", Next/bitstring>>, Accu) -> - decode0(Next, [<<13:5>>|Accu]); + decode0(Next, [<<13:5>> | Accu]); decode0(<<"d", Next/bitstring>>, Accu) -> - decode0(Next, [<<13:5>>|Accu]); + decode0(Next, [<<13:5>> | Accu]); decode0(<<"E", Next/bitstring>>, Accu) -> - decode0(Next, [<<14:5>>|Accu]); + decode0(Next, [<<14:5>> | Accu]); decode0(<<"e", Next/bitstring>>, Accu) -> - decode0(Next, [<<14:5>>|Accu]); + decode0(Next, [<<14:5>> | Accu]); decode0(<<"F", Next/bitstring>>, Accu) -> - decode0(Next, [<<15:5>>|Accu]); + decode0(Next, [<<15:5>> | Accu]); decode0(<<"f", Next/bitstring>>, Accu) -> - decode0(Next, [<<15:5>>|Accu]); + decode0(Next, [<<15:5>> | Accu]); decode0(<<"G", Next/bitstring>>, Accu) -> - decode0(Next, [<<16:5>>|Accu]); + decode0(Next, [<<16:5>> | Accu]); decode0(<<"g", Next/bitstring>>, Accu) -> - decode0(Next, [<<16:5>>|Accu]); + decode0(Next, [<<16:5>> | Accu]); decode0(<<"H", Next/bitstring>>, Accu) -> - decode0(Next, [<<17:5>>|Accu]); + decode0(Next, [<<17:5>> | Accu]); decode0(<<"h", Next/bitstring>>, Accu) -> - decode0(Next, [<<17:5>>|Accu]); + decode0(Next, [<<17:5>> | Accu]); decode0(<<"J", Next/bitstring>>, Accu) -> - decode0(Next, [<<18:5>>|Accu]); + decode0(Next, [<<18:5>> | Accu]); decode0(<<"j", Next/bitstring>>, Accu) -> - decode0(Next, [<<18:5>>|Accu]); + decode0(Next, [<<18:5>> | Accu]); decode0(<<"K", Next/bitstring>>, Accu) -> - decode0(Next, [<<19:5>>|Accu]); + decode0(Next, [<<19:5>> | Accu]); decode0(<<"k", Next/bitstring>>, Accu) -> - decode0(Next, [<<19:5>>|Accu]); + decode0(Next, [<<19:5>> | Accu]); decode0(<<"M", Next/bitstring>>, Accu) -> - decode0(Next, [<<20:5>>|Accu]); + decode0(Next, [<<20:5>> | Accu]); decode0(<<"m", Next/bitstring>>, Accu) -> - decode0(Next, [<<20:5>>|Accu]); + decode0(Next, [<<20:5>> | Accu]); decode0(<<"N", Next/bitstring>>, Accu) -> - decode0(Next, [<<21:5>>|Accu]); + decode0(Next, [<<21:5>> | Accu]); decode0(<<"n", Next/bitstring>>, Accu) -> - decode0(Next, [<<21:5>>|Accu]); + decode0(Next, [<<21:5>> | Accu]); decode0(<<"P", Next/bitstring>>, Accu) -> - decode0(Next, [<<22:5>>|Accu]); + decode0(Next, [<<22:5>> | Accu]); decode0(<<"p", Next/bitstring>>, Accu) -> - decode0(Next, [<<22:5>>|Accu]); + decode0(Next, [<<22:5>> | Accu]); decode0(<<"Q", Next/bitstring>>, Accu) -> - decode0(Next, [<<23:5>>|Accu]); + decode0(Next, [<<23:5>> | Accu]); decode0(<<"q", Next/bitstring>>, Accu) -> - decode0(Next, [<<23:5>>|Accu]); + decode0(Next, [<<23:5>> | Accu]); decode0(<<"R", Next/bitstring>>, Accu) -> - decode0(Next, [<<24:5>>|Accu]); + decode0(Next, [<<24:5>> | Accu]); decode0(<<"r", Next/bitstring>>, Accu) -> - decode0(Next, [<<24:5>>|Accu]); + decode0(Next, [<<24:5>> | Accu]); decode0(<<"S", Next/bitstring>>, Accu) -> - decode0(Next, [<<25:5>>|Accu]); + decode0(Next, [<<25:5>> | Accu]); decode0(<<"s", Next/bitstring>>, Accu) -> - decode0(Next, [<<25:5>>|Accu]); + decode0(Next, [<<25:5>> | Accu]); decode0(<<"T", Next/bitstring>>, Accu) -> - decode0(Next, [<<26:5>>|Accu]); + decode0(Next, [<<26:5>> | Accu]); decode0(<<"t", Next/bitstring>>, Accu) -> - decode0(Next, [<<26:5>>|Accu]); + decode0(Next, [<<26:5>> | Accu]); decode0(<<"V", Next/bitstring>>, Accu) -> - decode0(Next, [<<27:5>>|Accu]); + decode0(Next, [<<27:5>> | Accu]); decode0(<<"v", Next/bitstring>>, Accu) -> - decode0(Next, [<<27:5>>|Accu]); + decode0(Next, [<<27:5>> | Accu]); decode0(<<"W", Next/bitstring>>, Accu) -> - decode0(Next, [<<28:5>>|Accu]); + decode0(Next, [<<28:5>> | Accu]); decode0(<<"w", Next/bitstring>>, Accu) -> - decode0(Next, [<<28:5>>|Accu]); + decode0(Next, [<<28:5>> | Accu]); decode0(<<"X", Next/bitstring>>, Accu) -> - decode0(Next, [<<29:5>>|Accu]); + decode0(Next, [<<29:5>> | Accu]); decode0(<<"x", Next/bitstring>>, Accu) -> - decode0(Next, [<<29:5>>|Accu]); + decode0(Next, [<<29:5>> | Accu]); decode0(<<"Y", Next/bitstring>>, Accu) -> - decode0(Next, [<<30:5>>|Accu]); + decode0(Next, [<<30:5>> | Accu]); decode0(<<"y", Next/bitstring>>, Accu) -> - decode0(Next, [<<30:5>>|Accu]); + decode0(Next, [<<30:5>> | Accu]); decode0(<<"Z", Next/bitstring>>, Accu) -> - decode0(Next, [<<31:5>>|Accu]); + decode0(Next, [<<31:5>> | Accu]); decode0(<<"z", Next/bitstring>>, Accu) -> - decode0(Next, [<<31:5>>|Accu]); + decode0(Next, [<<31:5>> | Accu]); decode0(<<"-", Next/bitstring>>, Accu) -> decode0(Next, Accu). - diff --git a/src/base32_rfc4648.erl b/src/base32_rfc4648.erl index 8bfdaf8..8d778fd 100644 --- a/src/base32_rfc4648.erl +++ b/src/base32_rfc4648.erl @@ -4,292 +4,297 @@ -import(base32_utils, [rev_bits_list_to_binary/1]). + -spec encode(binary()) -> binary(). encode(Data) -> list_to_binary(encode0(Data)). + encode0(Data) -> Size = bit_size(Data), RevEncoded = case 40 - (Size rem 40) of - 40 -> - encode1(Data, []); - 32 -> - [$=, $=, $=, $=, $=, $=|encode1(Data, [])]; - 24 -> - [$=, $=, $=, $=|encode1(Data, [])]; - 16 -> - [$=, $=, $=|encode1(Data, [])]; - 8 -> - [$=|encode1(Data, [])] - end, + 40 -> + encode1(Data, []); + 32 -> + [$=, $=, $=, $=, $=, $= | encode1(Data, [])]; + 24 -> + [$=, $=, $=, $= | encode1(Data, [])]; + 16 -> + [$=, $=, $= | encode1(Data, [])]; + 8 -> + [$= | encode1(Data, [])] + end, lists:reverse(RevEncoded). + encode1(<<>>, Accu) -> Accu; encode1(<<0:5, Next/bitstring>>, Accu) -> - encode1(Next, [$A|Accu]); + encode1(Next, [$A | Accu]); encode1(<<1:5, Next/bitstring>>, Accu) -> - encode1(Next, [$B|Accu]); + encode1(Next, [$B | Accu]); encode1(<<2:5, Next/bitstring>>, Accu) -> - encode1(Next, [$C|Accu]); + encode1(Next, [$C | Accu]); encode1(<<3:5, Next/bitstring>>, Accu) -> - encode1(Next, [$D|Accu]); + encode1(Next, [$D | Accu]); encode1(<<4:5, Next/bitstring>>, Accu) -> - encode1(Next, [$E|Accu]); + encode1(Next, [$E | Accu]); encode1(<<5:5, Next/bitstring>>, Accu) -> - encode1(Next, [$F|Accu]); + encode1(Next, [$F | Accu]); encode1(<<6:5, Next/bitstring>>, Accu) -> - encode1(Next, [$G|Accu]); + encode1(Next, [$G | Accu]); encode1(<<7:5, Next/bitstring>>, Accu) -> - encode1(Next, [$H|Accu]); + encode1(Next, [$H | Accu]); encode1(<<8:5, Next/bitstring>>, Accu) -> - encode1(Next, [$I|Accu]); + encode1(Next, [$I | Accu]); encode1(<<9:5, Next/bitstring>>, Accu) -> - encode1(Next, [$J|Accu]); + encode1(Next, [$J | Accu]); encode1(<<10:5, Next/bitstring>>, Accu) -> - encode1(Next, [$K|Accu]); + encode1(Next, [$K | Accu]); encode1(<<11:5, Next/bitstring>>, Accu) -> - encode1(Next, [$L|Accu]); + encode1(Next, [$L | Accu]); encode1(<<12:5, Next/bitstring>>, Accu) -> - encode1(Next, [$M|Accu]); + encode1(Next, [$M | Accu]); encode1(<<13:5, Next/bitstring>>, Accu) -> - encode1(Next, [$N|Accu]); + encode1(Next, [$N | Accu]); encode1(<<14:5, Next/bitstring>>, Accu) -> - encode1(Next, [$O|Accu]); + encode1(Next, [$O | Accu]); encode1(<<15:5, Next/bitstring>>, Accu) -> - encode1(Next, [$P|Accu]); + encode1(Next, [$P | Accu]); encode1(<<16:5, Next/bitstring>>, Accu) -> - encode1(Next, [$Q|Accu]); + encode1(Next, [$Q | Accu]); encode1(<<17:5, Next/bitstring>>, Accu) -> - encode1(Next, [$R|Accu]); + encode1(Next, [$R | Accu]); encode1(<<18:5, Next/bitstring>>, Accu) -> - encode1(Next, [$S|Accu]); + encode1(Next, [$S | Accu]); encode1(<<19:5, Next/bitstring>>, Accu) -> - encode1(Next, [$T|Accu]); + encode1(Next, [$T | Accu]); encode1(<<20:5, Next/bitstring>>, Accu) -> - encode1(Next, [$U|Accu]); + encode1(Next, [$U | Accu]); encode1(<<21:5, Next/bitstring>>, Accu) -> - encode1(Next, [$V|Accu]); + encode1(Next, [$V | Accu]); encode1(<<22:5, Next/bitstring>>, Accu) -> - encode1(Next, [$W|Accu]); + encode1(Next, [$W | Accu]); encode1(<<23:5, Next/bitstring>>, Accu) -> - encode1(Next, [$X|Accu]); + encode1(Next, [$X | Accu]); encode1(<<24:5, Next/bitstring>>, Accu) -> - encode1(Next, [$Y|Accu]); + encode1(Next, [$Y | Accu]); encode1(<<25:5, Next/bitstring>>, Accu) -> - encode1(Next, [$Z|Accu]); + encode1(Next, [$Z | Accu]); encode1(<<26:5, Next/bitstring>>, Accu) -> - encode1(Next, [$2|Accu]); + encode1(Next, [$2 | Accu]); encode1(<<27:5, Next/bitstring>>, Accu) -> - encode1(Next, [$3|Accu]); + encode1(Next, [$3 | Accu]); encode1(<<28:5, Next/bitstring>>, Accu) -> - encode1(Next, [$4|Accu]); + encode1(Next, [$4 | Accu]); encode1(<<29:5, Next/bitstring>>, Accu) -> - encode1(Next, [$5|Accu]); + encode1(Next, [$5 | Accu]); encode1(<<30:5, Next/bitstring>>, Accu) -> - encode1(Next, [$6|Accu]); + encode1(Next, [$6 | Accu]); encode1(<<31:5, Next/bitstring>>, Accu) -> - encode1(Next, [$7|Accu]); + encode1(Next, [$7 | Accu]); encode1(<<0:4>>, Accu) -> - [$A|Accu]; + [$A | Accu]; encode1(<<1:4>>, Accu) -> - [$C|Accu]; + [$C | Accu]; encode1(<<2:4>>, Accu) -> - [$E|Accu]; + [$E | Accu]; encode1(<<3:4>>, Accu) -> - [$G|Accu]; + [$G | Accu]; encode1(<<4:4>>, Accu) -> - [$I|Accu]; + [$I | Accu]; encode1(<<5:4>>, Accu) -> - [$K|Accu]; + [$K | Accu]; encode1(<<6:4>>, Accu) -> - [$M|Accu]; + [$M | Accu]; encode1(<<7:4>>, Accu) -> - [$O|Accu]; + [$O | Accu]; encode1(<<8:4>>, Accu) -> - [$Q|Accu]; + [$Q | Accu]; encode1(<<9:4>>, Accu) -> - [$S|Accu]; + [$S | Accu]; encode1(<<10:4>>, Accu) -> - [$U|Accu]; + [$U | Accu]; encode1(<<11:4>>, Accu) -> - [$W|Accu]; + [$W | Accu]; encode1(<<12:4>>, Accu) -> - [$Y|Accu]; + [$Y | Accu]; encode1(<<13:4>>, Accu) -> - [$2|Accu]; + [$2 | Accu]; encode1(<<14:4>>, Accu) -> - [$4|Accu]; + [$4 | Accu]; encode1(<<15:4>>, Accu) -> - [$6|Accu]; + [$6 | Accu]; encode1(<<0:3>>, Accu) -> - [$A|Accu]; + [$A | Accu]; encode1(<<1:3>>, Accu) -> - [$E|Accu]; + [$E | Accu]; encode1(<<2:3>>, Accu) -> - [$I|Accu]; + [$I | Accu]; encode1(<<3:3>>, Accu) -> - [$M|Accu]; + [$M | Accu]; encode1(<<4:3>>, Accu) -> - [$Q|Accu]; + [$Q | Accu]; encode1(<<5:3>>, Accu) -> - [$U|Accu]; + [$U | Accu]; encode1(<<6:3>>, Accu) -> - [$Y|Accu]; + [$Y | Accu]; encode1(<<7:3>>, Accu) -> - [$4|Accu]; + [$4 | Accu]; encode1(<<0:2>>, Accu) -> - [$A|Accu]; + [$A | Accu]; encode1(<<1:2>>, Accu) -> - [$I|Accu]; + [$I | Accu]; encode1(<<2:2>>, Accu) -> - [$Q|Accu]; + [$Q | Accu]; encode1(<<3:2>>, Accu) -> - [$Y|Accu]; + [$Y | Accu]; encode1(<<0:1>>, Accu) -> - [$A|Accu]; + [$A | Accu]; encode1(<<1:1>>, Accu) -> - [$Q|Accu]. + [$Q | Accu]. + -spec decode(binary()) -> {ok, binary()} | {error, atom()}. decode(Data) -> decode0(Data, []). + decode0(<<>>, Accu) -> {ok, rev_bits_list_to_binary(Accu)}; decode0(<<"A", Next/bitstring>>, Accu) -> - decode0(Next, [<<0:5>>|Accu]); + decode0(Next, [<<0:5>> | Accu]); decode0(<<"B", Next/bitstring>>, Accu) -> - decode0(Next, [<<1:5>>|Accu]); + decode0(Next, [<<1:5>> | Accu]); decode0(<<"C", Next/bitstring>>, Accu) -> - decode0(Next, [<<2:5>>|Accu]); + decode0(Next, [<<2:5>> | Accu]); decode0(<<"D", Next/bitstring>>, Accu) -> - decode0(Next, [<<3:5>>|Accu]); + decode0(Next, [<<3:5>> | Accu]); decode0(<<"E", Next/bitstring>>, Accu) -> - decode0(Next, [<<4:5>>|Accu]); + decode0(Next, [<<4:5>> | Accu]); decode0(<<"F", Next/bitstring>>, Accu) -> - decode0(Next, [<<5:5>>|Accu]); + decode0(Next, [<<5:5>> | Accu]); decode0(<<"G", Next/bitstring>>, Accu) -> - decode0(Next, [<<6:5>>|Accu]); + decode0(Next, [<<6:5>> | Accu]); decode0(<<"H", Next/bitstring>>, Accu) -> - decode0(Next, [<<7:5>>|Accu]); + decode0(Next, [<<7:5>> | Accu]); decode0(<<"I", Next/bitstring>>, Accu) -> - decode0(Next, [<<8:5>>|Accu]); + decode0(Next, [<<8:5>> | Accu]); decode0(<<"J", Next/bitstring>>, Accu) -> - decode0(Next, [<<9:5>>|Accu]); + decode0(Next, [<<9:5>> | Accu]); decode0(<<"K", Next/bitstring>>, Accu) -> - decode0(Next, [<<10:5>>|Accu]); + decode0(Next, [<<10:5>> | Accu]); decode0(<<"L", Next/bitstring>>, Accu) -> - decode0(Next, [<<11:5>>|Accu]); + decode0(Next, [<<11:5>> | Accu]); decode0(<<"M", Next/bitstring>>, Accu) -> - decode0(Next, [<<12:5>>|Accu]); + decode0(Next, [<<12:5>> | Accu]); decode0(<<"N", Next/bitstring>>, Accu) -> - decode0(Next, [<<13:5>>|Accu]); + decode0(Next, [<<13:5>> | Accu]); decode0(<<"O", Next/bitstring>>, Accu) -> - decode0(Next, [<<14:5>>|Accu]); + decode0(Next, [<<14:5>> | Accu]); decode0(<<"P", Next/bitstring>>, Accu) -> - decode0(Next, [<<15:5>>|Accu]); + decode0(Next, [<<15:5>> | Accu]); decode0(<<"Q", Next/bitstring>>, Accu) -> - decode0(Next, [<<16:5>>|Accu]); + decode0(Next, [<<16:5>> | Accu]); decode0(<<"R", Next/bitstring>>, Accu) -> - decode0(Next, [<<17:5>>|Accu]); + decode0(Next, [<<17:5>> | Accu]); decode0(<<"S", Next/bitstring>>, Accu) -> - decode0(Next, [<<18:5>>|Accu]); + decode0(Next, [<<18:5>> | Accu]); decode0(<<"T", Next/bitstring>>, Accu) -> - decode0(Next, [<<19:5>>|Accu]); + decode0(Next, [<<19:5>> | Accu]); decode0(<<"U", Next/bitstring>>, Accu) -> - decode0(Next, [<<20:5>>|Accu]); + decode0(Next, [<<20:5>> | Accu]); decode0(<<"V", Next/bitstring>>, Accu) -> - decode0(Next, [<<21:5>>|Accu]); + decode0(Next, [<<21:5>> | Accu]); decode0(<<"W", Next/bitstring>>, Accu) -> - decode0(Next, [<<22:5>>|Accu]); + decode0(Next, [<<22:5>> | Accu]); decode0(<<"X", Next/bitstring>>, Accu) -> - decode0(Next, [<<23:5>>|Accu]); + decode0(Next, [<<23:5>> | Accu]); decode0(<<"Y", Next/bitstring>>, Accu) -> - decode0(Next, [<<24:5>>|Accu]); + decode0(Next, [<<24:5>> | Accu]); decode0(<<"Z", Next/bitstring>>, Accu) -> - decode0(Next, [<<25:5>>|Accu]); + decode0(Next, [<<25:5>> | Accu]); decode0(<<"2", Next/bitstring>>, Accu) -> - decode0(Next, [<<26:5>>|Accu]); + decode0(Next, [<<26:5>> | Accu]); decode0(<<"3", Next/bitstring>>, Accu) -> - decode0(Next, [<<27:5>>|Accu]); + decode0(Next, [<<27:5>> | Accu]); decode0(<<"4", Next/bitstring>>, Accu) -> - decode0(Next, [<<28:5>>|Accu]); + decode0(Next, [<<28:5>> | Accu]); decode0(<<"5", Next/bitstring>>, Accu) -> - decode0(Next, [<<29:5>>|Accu]); + decode0(Next, [<<29:5>> | Accu]); decode0(<<"6", Next/bitstring>>, Accu) -> - decode0(Next, [<<30:5>>|Accu]); + decode0(Next, [<<30:5>> | Accu]); decode0(<<"7", Next/bitstring>>, Accu) -> - decode0(Next, [<<31:5>>|Accu]); + decode0(Next, [<<31:5>> | Accu]); -decode0(<<"======">>, [<<0:5>>|Accu]) -> - decode0(<<>>, [<<0:3>>|Accu]); -decode0(<<"======">>, [<<4:5>>|Accu]) -> - decode0(<<>>, [<<1:3>>|Accu]); -decode0(<<"======">>, [<<8:5>>|Accu]) -> - decode0(<<>>, [<<2:3>>|Accu]); -decode0(<<"======">>, [<<12:5>>|Accu]) -> - decode0(<<>>, [<<3:3>>|Accu]); -decode0(<<"======">>, [<<16:5>>|Accu]) -> - decode0(<<>>, [<<4:3>>|Accu]); -decode0(<<"======">>, [<<20:5>>|Accu]) -> - decode0(<<>>, [<<5:3>>|Accu]); -decode0(<<"======">>, [<<24:5>>|Accu]) -> - decode0(<<>>, [<<6:3>>|Accu]); -decode0(<<"======">>, [<<28:5>>|Accu]) -> - decode0(<<>>, [<<7:3>>|Accu]); +decode0(<<"======">>, [<<0:5>> | Accu]) -> + decode0(<<>>, [<<0:3>> | Accu]); +decode0(<<"======">>, [<<4:5>> | Accu]) -> + decode0(<<>>, [<<1:3>> | Accu]); +decode0(<<"======">>, [<<8:5>> | Accu]) -> + decode0(<<>>, [<<2:3>> | Accu]); +decode0(<<"======">>, [<<12:5>> | Accu]) -> + decode0(<<>>, [<<3:3>> | Accu]); +decode0(<<"======">>, [<<16:5>> | Accu]) -> + decode0(<<>>, [<<4:3>> | Accu]); +decode0(<<"======">>, [<<20:5>> | Accu]) -> + decode0(<<>>, [<<5:3>> | Accu]); +decode0(<<"======">>, [<<24:5>> | Accu]) -> + decode0(<<>>, [<<6:3>> | Accu]); +decode0(<<"======">>, [<<28:5>> | Accu]) -> + decode0(<<>>, [<<7:3>> | Accu]); -decode0(<<"====">>, [<<0:5>>|Accu]) -> - decode0(<<>>, [<<0:1>>|Accu]); -decode0(<<"====">>, [<<16:5>>|Accu]) -> - decode0(<<>>, [<<1:1>>|Accu]); +decode0(<<"====">>, [<<0:5>> | Accu]) -> + decode0(<<>>, [<<0:1>> | Accu]); +decode0(<<"====">>, [<<16:5>> | Accu]) -> + decode0(<<>>, [<<1:1>> | Accu]); -decode0(<<"===">>, [<<0:5>>|Accu]) -> - decode0(<<>>, [<<0:4>>|Accu]); -decode0(<<"===">>, [<<2:5>>|Accu]) -> - decode0(<<>>, [<<1:4>>|Accu]); -decode0(<<"===">>, [<<4:5>>|Accu]) -> - decode0(<<>>, [<<2:4>>|Accu]); -decode0(<<"===">>, [<<6:5>>|Accu]) -> - decode0(<<>>, [<<3:4>>|Accu]); -decode0(<<"===">>, [<<8:5>>|Accu]) -> - decode0(<<>>, [<<4:4>>|Accu]); -decode0(<<"===">>, [<<10:5>>|Accu]) -> - decode0(<<>>, [<<5:4>>|Accu]); -decode0(<<"===">>, [<<12:5>>|Accu]) -> - decode0(<<>>, [<<6:4>>|Accu]); -decode0(<<"===">>, [<<14:5>>|Accu]) -> - decode0(<<>>, [<<7:4>>|Accu]); -decode0(<<"===">>, [<<16:5>>|Accu]) -> - decode0(<<>>, [<<8:4>>|Accu]); -decode0(<<"===">>, [<<18:5>>|Accu]) -> - decode0(<<>>, [<<9:4>>|Accu]); -decode0(<<"===">>, [<<20:5>>|Accu]) -> - decode0(<<>>, [<<10:4>>|Accu]); -decode0(<<"===">>, [<<22:5>>|Accu]) -> - decode0(<<>>, [<<11:4>>|Accu]); -decode0(<<"===">>, [<<24:5>>|Accu]) -> - decode0(<<>>, [<<12:4>>|Accu]); -decode0(<<"===">>, [<<26:5>>|Accu]) -> - decode0(<<>>, [<<13:4>>|Accu]); -decode0(<<"===">>, [<<28:5>>|Accu]) -> - decode0(<<>>, [<<14:4>>|Accu]); -decode0(<<"===">>, [<<30:5>>|Accu]) -> - decode0(<<>>, [<<15:4>>|Accu]); +decode0(<<"===">>, [<<0:5>> | Accu]) -> + decode0(<<>>, [<<0:4>> | Accu]); +decode0(<<"===">>, [<<2:5>> | Accu]) -> + decode0(<<>>, [<<1:4>> | Accu]); +decode0(<<"===">>, [<<4:5>> | Accu]) -> + decode0(<<>>, [<<2:4>> | Accu]); +decode0(<<"===">>, [<<6:5>> | Accu]) -> + decode0(<<>>, [<<3:4>> | Accu]); +decode0(<<"===">>, [<<8:5>> | Accu]) -> + decode0(<<>>, [<<4:4>> | Accu]); +decode0(<<"===">>, [<<10:5>> | Accu]) -> + decode0(<<>>, [<<5:4>> | Accu]); +decode0(<<"===">>, [<<12:5>> | Accu]) -> + decode0(<<>>, [<<6:4>> | Accu]); +decode0(<<"===">>, [<<14:5>> | Accu]) -> + decode0(<<>>, [<<7:4>> | Accu]); +decode0(<<"===">>, [<<16:5>> | Accu]) -> + decode0(<<>>, [<<8:4>> | Accu]); +decode0(<<"===">>, [<<18:5>> | Accu]) -> + decode0(<<>>, [<<9:4>> | Accu]); +decode0(<<"===">>, [<<20:5>> | Accu]) -> + decode0(<<>>, [<<10:4>> | Accu]); +decode0(<<"===">>, [<<22:5>> | Accu]) -> + decode0(<<>>, [<<11:4>> | Accu]); +decode0(<<"===">>, [<<24:5>> | Accu]) -> + decode0(<<>>, [<<12:4>> | Accu]); +decode0(<<"===">>, [<<26:5>> | Accu]) -> + decode0(<<>>, [<<13:4>> | Accu]); +decode0(<<"===">>, [<<28:5>> | Accu]) -> + decode0(<<>>, [<<14:4>> | Accu]); +decode0(<<"===">>, [<<30:5>> | Accu]) -> + decode0(<<>>, [<<15:4>> | Accu]); -decode0(<<"=">>, [<<0:5>>|Accu]) -> - decode0(<<>>, [<<0:2>>|Accu]); -decode0(<<"=">>, [<<8:5>>|Accu]) -> - decode0(<<>>, [<<1:2>>|Accu]); -decode0(<<"=">>, [<<16:5>>|Accu]) -> - decode0(<<>>, [<<2:2>>|Accu]); -decode0(<<"=">>, [<<24:5>>|Accu]) -> - decode0(<<>>, [<<3:2>>|Accu]); +decode0(<<"=">>, [<<0:5>> | Accu]) -> + decode0(<<>>, [<<0:2>> | Accu]); +decode0(<<"=">>, [<<8:5>> | Accu]) -> + decode0(<<>>, [<<1:2>> | Accu]); +decode0(<<"=">>, [<<16:5>> | Accu]) -> + decode0(<<>>, [<<2:2>> | Accu]); +decode0(<<"=">>, [<<24:5>> | Accu]) -> + decode0(<<>>, [<<3:2>> | Accu]); decode0(_, _) -> {error, invalid_format}. diff --git a/src/base32_utils.erl b/src/base32_utils.erl index 6236aa4..a7f0100 100644 --- a/src/base32_utils.erl +++ b/src/base32_utils.erl @@ -2,18 +2,22 @@ -export([rev_bits_list_to_binary/1, bits_list_size/1]). + rev_bits_list_to_binary(List) -> rev_bits_list_to_binary0(List, <<>>). + rev_bits_list_to_binary0([], Accu) -> Accu; -rev_bits_list_to_binary0([Bits|Next], Accu) -> +rev_bits_list_to_binary0([Bits | Next], Accu) -> rev_bits_list_to_binary0(Next, <>). + bits_list_size(List) -> bits_list_size0(List, 0). + bits_list_size0([], Count) -> Count; -bits_list_size0([Bits|Next], Count) -> +bits_list_size0([Bits | Next], Count) -> bits_list_size0(Next, bit_size(Bits) + Count). diff --git a/test/base32_clockwork_test.erl b/test/base32_clockwork_test.erl index 67d00a7..bd2f3a4 100644 --- a/test/base32_clockwork_test.erl +++ b/test/base32_clockwork_test.erl @@ -4,6 +4,7 @@ -import(base32_clockwork, [encode/1, decode/1]). + encode_test() -> ?assertEqual(<<>>, encode(<<>>)), ?assertEqual(<<"CR">>, encode(<<"f">>)), @@ -13,10 +14,11 @@ encode_test() -> ?assertEqual(<<"CSQPYRK1">>, encode(<<"fooba">>)), ?assertEqual(<<"CSQPYRK1E8">>, encode(<<"foobar">>)), ?assertEqual(<<"07EKWRQY2N7DEAVD5MJ3JX36KM">>, - encode(<<1,221,62,98,254,21,78,215,43,109,45,36,57,116,102,157>>)), + encode(<<1, 221, 62, 98, 254, 21, 78, 215, 43, 109, 45, 36, 57, 116, 102, 157>>)), ?assertEqual(<<"AXQQEB10D5T20WK5C5P6RY90EXQQ4TVK44">>, encode(<<"Wow, it really works!">>)). + decode_test() -> ?assertEqual({ok, <<>>}, decode(<<>>)), ?assertEqual({ok, <<"f">>}, decode(<<"CR">>)), @@ -25,11 +27,12 @@ decode_test() -> ?assertEqual({ok, <<"foob">>}, decode(<<"CSQPYRG">>)), ?assertEqual({ok, <<"fooba">>}, decode(<<"CSQPYRK1">>)), ?assertEqual({ok, <<"foobar">>}, decode(<<"CSQPYRK1E8">>)), - ?assertEqual({ok, <<1,221,62,98,254,21,78,215,43,109,45,36,57,116,102,157>>}, + ?assertEqual({ok, <<1, 221, 62, 98, 254, 21, 78, 215, 43, 109, 45, 36, 57, 116, 102, 157>>}, decode(<<"07EKWRQY2N7DEAVD5MJ3JX36KM">>)), ?assertEqual({ok, <<"Wow, it really works!">>}, decode(<<"AXQQEB10D5T20WK5C5P6RY90EXQQ4TVK44">>)). + decode_error_test() -> ?assertEqual({error, invalid_size}, decode(<<"0">>)), ?assertEqual({error, invalid_format}, decode(<<"012*">>)). diff --git a/test/base32_crockford_test.erl b/test/base32_crockford_test.erl index 3ab4f48..0737272 100644 --- a/test/base32_crockford_test.erl +++ b/test/base32_crockford_test.erl @@ -2,10 +2,12 @@ -include_lib("eunit/include/eunit.hrl"). --import(base32_crockford, [encode/1, - encode_check/1, - decode/1, - decode_check/1]). +-import(base32_crockford, + [encode/1, + encode_check/1, + decode/1, + decode_check/1]). + encode_nocheck_test() -> ?assertEqual(<<"CR">>, encode(<<"f">>)), @@ -15,6 +17,7 @@ encode_nocheck_test() -> ?assertEqual(<<"CSQPYRK1">>, encode(<<"fooba">>)), ?assertEqual(<<"CSQPYRK1E8">>, encode(<<"foobar">>)). + encode_check_test() -> ?assertEqual(<<"CRW">>, encode_check(<<"f">>)), ?assertEqual(<<"CSQGV">>, encode_check(<<"fo">>)), @@ -23,6 +26,7 @@ encode_check_test() -> ?assertEqual(<<"CSQPYRK1U">>, encode_check(<<"fooba">>)), ?assertEqual(<<"CSQPYRK1E86">>, encode_check(<<"foobar">>)). + decode_nocheck_test() -> ?assertEqual(<<"f">>, decode(<<"CR">>)), ?assertEqual(<<"fo">>, decode(<<"CSQG">>)), @@ -31,6 +35,7 @@ decode_nocheck_test() -> ?assertEqual(<<"fooba">>, decode(<<"CSQPYRK1">>)), ?assertEqual(<<"foobar">>, decode(<<"CSQPYRK1E8">>)). + decode_check_test() -> ?assertEqual({ok, <<"f">>}, decode_check(<<"CRW">>)), ?assertEqual({ok, <<"fo">>}, decode_check(<<"CSQGV">>)), @@ -39,6 +44,7 @@ decode_check_test() -> ?assertEqual({ok, <<"fooba">>}, decode_check(<<"CSQPYRK1U">>)), ?assertEqual({ok, <<"foobar">>}, decode_check(<<"CSQPYRK1E86">>)). + decode_hyphen_test() -> ?assertEqual(<<"foobar">>, decode(<<"-CSQPYRK1E8">>)), ?assertEqual(<<"foobar">>, decode(<<"---CSQPYRK1E8">>)), @@ -49,13 +55,15 @@ decode_hyphen_test() -> ?assertEqual(<<"foobar">>, decode(<<"CSQ-PYR-K1E-8">>)), ?assertEqual(<<"foobar">>, decode(<<"CSQ--PYR--K1E--8">>)). + other1_test() -> - P = <<1,221,62,98,254,21,78,215,43,109,45,36,57,116,102,157>>, + P = <<1, 221, 62, 98, 254, 21, 78, 215, 43, 109, 45, 36, 57, 116, 102, 157>>, E = <<"07EKWRQY2N7DEAVD5MJ3JX36KM">>, ?assertEqual(E, encode(P)), ?assertEqual(P, decode(E)), ok. + other2_test() -> %% https://github.com/aiq/basexx/blob/master/test/crockford_spec.lua P = <<"Wow, it really works!">>, diff --git a/test/base32_rfc4648_test.erl b/test/base32_rfc4648_test.erl index a18c44c..15a9582 100644 --- a/test/base32_rfc4648_test.erl +++ b/test/base32_rfc4648_test.erl @@ -4,6 +4,7 @@ -import(base32_rfc4648, [encode/1, decode/1]). + encode_test() -> ?assertEqual(<<"MY======">>, encode(<<"f">>)), ?assertEqual(<<"MZXQ====">>, encode(<<"fo">>)), @@ -12,6 +13,7 @@ encode_test() -> ?assertEqual(<<"MZXW6YTB">>, encode(<<"fooba">>)), ?assertEqual(<<"MZXW6YTBOI======">>, encode(<<"foobar">>)). + decode_test() -> ?assertEqual({ok, <<"f">>}, decode(<<"MY======">>)), ?assertEqual({ok, <<"fo">>}, decode(<<"MZXQ====">>)), @@ -20,6 +22,6 @@ decode_test() -> ?assertEqual({ok, <<"fooba">>}, decode(<<"MZXW6YTB">>)), ?assertEqual({ok, <<"foobar">>}, decode(<<"MZXW6YTBOI======">>)). + decode_error_test() -> ?assertEqual({error, invalid_format}, decode(<<"MZXW6YTBOI======A">>)). - diff --git a/test/base32_test.erl b/test/base32_test.erl index fafa760..1d964c1 100644 --- a/test/base32_test.erl +++ b/test/base32_test.erl @@ -4,6 +4,7 @@ -import(base32, [encode/2, decode/2]). + rfc4648_test() -> Data = <<"foobar">>, Encoded = encode(rfc4648, Data), @@ -11,10 +12,10 @@ rfc4648_test() -> ?assertEqual(Encoded, base32_rfc4648:encode(Data)), ?assertEqual(Decoded, base32_rfc4648:decode(Encoded)). + crockford_nocheck_test() -> Data = <<"foobar">>, Encoded = encode(crockford, Data), {ok, Decoded} = decode(crockford, Encoded), ?assertEqual(Encoded, base32_crockford:encode(Data)), ?assertEqual(Decoded, base32_crockford:decode(Encoded)). -