|
| 1 | +%% Copyright 2011 Steve Davis <steve@simulacity.com> |
| 2 | +% |
| 3 | +% Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +% you may not use this file except in compliance with the License. |
| 5 | +% You may obtain a copy of the License at |
| 6 | +% |
| 7 | +% http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +% |
| 9 | +% Unless required by applicable law or agreed to in writing, software |
| 10 | +% distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +% See the License for the specific language governing permissions and |
| 13 | +% limitations under the License. |
| 14 | + |
| 15 | +-module(base32). |
| 16 | + |
| 17 | +-export([encode/1, decode/1]). |
| 18 | + |
| 19 | +-define(BASE32_ALPHABET, { |
| 20 | + $A, $B, $C, $D, $E, $F, $G, $H, |
| 21 | + $I, $J, $K, $L, $M, $N, $O, $P, |
| 22 | + $Q, $R, $S, $T, $U, $V, $W, $X, |
| 23 | + $Y, $Z, $2, $3, $4, $5, $6, $7 |
| 24 | +}). |
| 25 | + |
| 26 | +%% RFC 4648 |
| 27 | + |
| 28 | +%% |
| 29 | +encode(Bin) when is_binary(Bin) -> |
| 30 | + Split = 5 * (byte_size(Bin) div 5), |
| 31 | + <<Main0:Split/binary, Rest/binary>> = Bin, |
| 32 | + Main = << <<(b32e(C))>> || <<C:5>> <= Main0 >>, |
| 33 | + encode0(Rest, Main). |
| 34 | + |
| 35 | +encode0(<<>>, Acc) -> |
| 36 | + Acc; |
| 37 | +encode0(<<A:5, B:3>>, Acc) -> |
| 38 | + <<Acc/binary, (b32e(A)), (b32e(B bsl 2)), "======">>; |
| 39 | +encode0(<<A:5, B:5, C:5, D:1>>, Acc) -> |
| 40 | + <<Acc/binary, (b32e(A)), (b32e(B)), (b32e(C)), (b32e(D bsl 4)), "====">>; |
| 41 | +encode0(<<A:5, B:5, C:5, D:5, E:4>>, Acc) -> |
| 42 | + <<Acc/binary, (b32e(A)), (b32e(B)), (b32e(C)), (b32e(D)), (b32e(E bsl 1)), "===">>; |
| 43 | +encode0(<<A:5, B:5, C:5, D:5, E:5, F:5, G:2>>, Acc) -> |
| 44 | + <<Acc/binary, (b32e(A)), (b32e(B)), (b32e(C)), (b32e(D)), (b32e(E)), (b32e(F)), (b32e(G bsl 3)), "=">>. |
| 45 | + |
| 46 | +%% |
| 47 | +decode(Bin) when is_binary(Bin) -> |
| 48 | + Result = decode(Bin, <<>>), |
| 49 | + true = is_binary(Result), |
| 50 | + Result. |
| 51 | + |
| 52 | +decode(<<X, "======">>, Acc) -> |
| 53 | + Bits = decode0(X) bsr 2, |
| 54 | + <<Acc/bits, Bits:3>>; |
| 55 | +decode(<<X, "====">>, Acc) -> |
| 56 | + Bits = decode0(X) bsr 4, |
| 57 | + <<Acc/bits, Bits:1>>; |
| 58 | +decode(<<X, "===">>, Acc) -> |
| 59 | + Bits = decode0(X) bsr 1, |
| 60 | + <<Acc/bits, Bits:4>>; |
| 61 | +decode(<<X, "=">>, Acc) -> |
| 62 | + Bits = decode0(X) bsr 3, |
| 63 | + <<Acc/bits, Bits:2>>; |
| 64 | +decode(<<A, Bin/binary>>, Acc) -> |
| 65 | + Bits = decode0(A), |
| 66 | + decode(Bin, <<Acc/bits, Bits:5>>); |
| 67 | +decode(<<>>, Acc) -> |
| 68 | + true = is_binary(Acc), |
| 69 | + Acc. |
| 70 | + |
| 71 | +decode0(X) when X >= $A, X =< $Z -> |
| 72 | + X - $A; |
| 73 | +decode0(X) when X >= $2, X =< $7 -> |
| 74 | + X - $2 + 26. |
| 75 | + |
| 76 | +b32e(X) -> |
| 77 | + element(X + 1, ?BASE32_ALPHABET). |
| 78 | + |
| 79 | + |
0 commit comments