Add Erlang snippets
This commit is contained in:
parent
e1bec6b996
commit
e9ad453375
249
snippets/vb58.erl
Normal file
249
snippets/vb58.erl
Normal file
@ -0,0 +1,249 @@
|
||||
%% @doc
|
||||
%% Vanillae Base58 Encoding/Decoding module
|
||||
%%
|
||||
%% References
|
||||
%%
|
||||
%% 1. https://digitalbazaar.github.io/base58-spec/#encode
|
||||
%% 2. https://www.youtube.com/watch?v=GedV3S9X89c
|
||||
%% @end
|
||||
-module(vb58).
|
||||
|
||||
-export([enc/1, dec/1]).
|
||||
|
||||
%% TODO: move these cases to test or something
|
||||
%% this originated from the
|
||||
%%-mode(compile).
|
||||
%%-spec enc(binary()) -> string().
|
||||
%%% https://digitalbazaar.github.io/base58-spec/#encode
|
||||
%
|
||||
%main([]) ->
|
||||
% {ok, Cases} = file:consult("b58_cases_3.eterms"),
|
||||
% test_cases(Cases).
|
||||
%
|
||||
%test_cases([{{encoded, E}, {decoded, D}} | Rest]) ->
|
||||
% EncodeOk = E =:= enc(D),
|
||||
% DecodeOk = D =:= dec(E),
|
||||
% ok =
|
||||
% case EncodeOk of
|
||||
% true -> ok;
|
||||
% false -> io:format("===============================~n"
|
||||
% "YOU ARE A FAILURE TO ENCODE~n"
|
||||
% "===============================~n"
|
||||
% "decoded : ~tw~n"
|
||||
% "expected : ~ts~n"
|
||||
% "actual : ~ts~n~n",
|
||||
% [D, E, enc(D)])
|
||||
% end,
|
||||
% ok =
|
||||
% case DecodeOk of
|
||||
% true -> ok;
|
||||
% false -> io:format("===============================~n"
|
||||
% "YOU ARE A FAILURE TO DECODE~n"
|
||||
% "===============================~n"
|
||||
% "encoded : ~ts~n"
|
||||
% "expected : ~tw~n"
|
||||
% "actual : ~tw~n~n",
|
||||
% [E, D, dec(E)])
|
||||
% end,
|
||||
% test_cases(Rest);
|
||||
%test_cases([]) ->
|
||||
% ok.
|
||||
|
||||
% this was much clearer: https://www.youtube.com/watch?v=GedV3S9X89c
|
||||
|
||||
-spec enc(Bytes) -> Base58
|
||||
when Bytes :: binary(),
|
||||
Base58 :: string().
|
||||
%% @doc
|
||||
%% Encode a bytestring into base58 notation
|
||||
|
||||
enc(Bytes) ->
|
||||
% grab leading 0s
|
||||
{NumLeadingZeros, Rest} = split_zeros(Bytes, 0),
|
||||
NBitsInRest = bit_size(Rest),
|
||||
<<RestBigNum:NBitsInRest>> = Rest,
|
||||
ZerosBase58 = [$1 || _ <- lists:seq(1, NumLeadingZeros)],
|
||||
RestBase58 = enc(RestBigNum, []),
|
||||
ZerosBase58 ++ RestBase58.
|
||||
|
||||
|
||||
|
||||
-spec split_zeros(Bytes, InitZeros) -> {NumLeadingZeros, Rest}
|
||||
when Bytes :: binary(),
|
||||
InitZeros :: integer(),
|
||||
NumLeadingZeros :: binary(),
|
||||
Rest :: binary().
|
||||
|
||||
split_zeros(<<0:8, Rest/binary>>, NumZerosAcc) ->
|
||||
NewNumZerosAcc = NumZerosAcc + 1,
|
||||
split_zeros(Rest, NewNumZerosAcc);
|
||||
split_zeros(Rest, NumZerosAcc) ->
|
||||
{NumZerosAcc, Rest}.
|
||||
|
||||
|
||||
|
||||
-spec enc(BytesBigNum, Base58Acc) -> Base58
|
||||
when BytesBigNum :: integer(),
|
||||
Base58Acc :: [0..57],
|
||||
Base58 :: string().
|
||||
|
||||
enc(0, Acc) ->
|
||||
lists:map(fun int2char/1, Acc);
|
||||
enc(BitNum, Acc) ->
|
||||
Q = BitNum div 58,
|
||||
R = BitNum rem 58,
|
||||
enc(Q, [R | Acc]).
|
||||
|
||||
|
||||
|
||||
-spec dec(Base58) -> DecodedBytes
|
||||
when Base58 :: string(),
|
||||
DecodedBytes :: binary().
|
||||
%% @doc
|
||||
%% Decode a Base58-encoded string into a bytestring
|
||||
|
||||
dec(Str) ->
|
||||
% the number of leading 1s tells us the number of leading zeros
|
||||
{NumLeadingZeros, RestStr} = split_ones(Str, 0),
|
||||
LeadingZeros = << <<0>> || _ <- lists:seq(1, NumLeadingZeros) >>,
|
||||
RestNs = lists:map(fun char2int/1, RestStr),
|
||||
RestBytes = dec(RestNs, 0),
|
||||
<<LeadingZeros/binary, RestBytes/binary>>.
|
||||
|
||||
split_ones([$1 | Rest], NOnes) ->
|
||||
split_ones(Rest, NOnes + 1);
|
||||
split_ones(B58Str, NOnes) ->
|
||||
{NOnes, B58Str}.
|
||||
|
||||
|
||||
dec([N | Ns], Acc) ->
|
||||
NewAcc = (Acc*58) + N,
|
||||
dec(Ns, NewAcc);
|
||||
dec([], FinalAccN) ->
|
||||
bignum_to_binary_bige(FinalAccN, <<>>).
|
||||
|
||||
bignum_to_binary_bige(0, Acc) ->
|
||||
Acc;
|
||||
bignum_to_binary_bige(N, Acc) ->
|
||||
Q = N div 256,
|
||||
R = N rem 256,
|
||||
NewAcc = <<R, Acc/binary>>,
|
||||
bignum_to_binary_bige(Q, NewAcc).
|
||||
|
||||
int2char( 0) -> $1;
|
||||
int2char( 1) -> $2;
|
||||
int2char( 2) -> $3;
|
||||
int2char( 3) -> $4;
|
||||
int2char( 4) -> $5;
|
||||
int2char( 5) -> $6;
|
||||
int2char( 6) -> $7;
|
||||
int2char( 7) -> $8;
|
||||
int2char( 8) -> $9;
|
||||
int2char( 9) -> $A;
|
||||
int2char(10) -> $B;
|
||||
int2char(11) -> $C;
|
||||
int2char(12) -> $D;
|
||||
int2char(13) -> $E;
|
||||
int2char(14) -> $F;
|
||||
int2char(15) -> $G;
|
||||
int2char(16) -> $H;
|
||||
int2char(17) -> $J;
|
||||
int2char(18) -> $K;
|
||||
int2char(19) -> $L;
|
||||
int2char(20) -> $M;
|
||||
int2char(21) -> $N;
|
||||
int2char(22) -> $P;
|
||||
int2char(23) -> $Q;
|
||||
int2char(24) -> $R;
|
||||
int2char(25) -> $S;
|
||||
int2char(26) -> $T;
|
||||
int2char(27) -> $U;
|
||||
int2char(28) -> $V;
|
||||
int2char(29) -> $W;
|
||||
int2char(30) -> $X;
|
||||
int2char(31) -> $Y;
|
||||
int2char(32) -> $Z;
|
||||
int2char(33) -> $a;
|
||||
int2char(34) -> $b;
|
||||
int2char(35) -> $c;
|
||||
int2char(36) -> $d;
|
||||
int2char(37) -> $e;
|
||||
int2char(38) -> $f;
|
||||
int2char(39) -> $g;
|
||||
int2char(40) -> $h;
|
||||
int2char(41) -> $i;
|
||||
int2char(42) -> $j;
|
||||
int2char(43) -> $k;
|
||||
int2char(44) -> $m;
|
||||
int2char(45) -> $n;
|
||||
int2char(46) -> $o;
|
||||
int2char(47) -> $p;
|
||||
int2char(48) -> $q;
|
||||
int2char(49) -> $r;
|
||||
int2char(50) -> $s;
|
||||
int2char(51) -> $t;
|
||||
int2char(52) -> $u;
|
||||
int2char(53) -> $v;
|
||||
int2char(54) -> $w;
|
||||
int2char(55) -> $x;
|
||||
int2char(56) -> $y;
|
||||
int2char(57) -> $z.
|
||||
|
||||
char2int($1) -> 0;
|
||||
char2int($2) -> 1;
|
||||
char2int($3) -> 2;
|
||||
char2int($4) -> 3;
|
||||
char2int($5) -> 4;
|
||||
char2int($6) -> 5;
|
||||
char2int($7) -> 6;
|
||||
char2int($8) -> 7;
|
||||
char2int($9) -> 8;
|
||||
char2int($A) -> 9;
|
||||
char2int($B) -> 10;
|
||||
char2int($C) -> 11;
|
||||
char2int($D) -> 12;
|
||||
char2int($E) -> 13;
|
||||
char2int($F) -> 14;
|
||||
char2int($G) -> 15;
|
||||
char2int($H) -> 16;
|
||||
char2int($J) -> 17;
|
||||
char2int($K) -> 18;
|
||||
char2int($L) -> 19;
|
||||
char2int($M) -> 20;
|
||||
char2int($N) -> 21;
|
||||
char2int($P) -> 22;
|
||||
char2int($Q) -> 23;
|
||||
char2int($R) -> 24;
|
||||
char2int($S) -> 25;
|
||||
char2int($T) -> 26;
|
||||
char2int($U) -> 27;
|
||||
char2int($V) -> 28;
|
||||
char2int($W) -> 29;
|
||||
char2int($X) -> 30;
|
||||
char2int($Y) -> 31;
|
||||
char2int($Z) -> 32;
|
||||
char2int($a) -> 33;
|
||||
char2int($b) -> 34;
|
||||
char2int($c) -> 35;
|
||||
char2int($d) -> 36;
|
||||
char2int($e) -> 37;
|
||||
char2int($f) -> 38;
|
||||
char2int($g) -> 39;
|
||||
char2int($h) -> 40;
|
||||
char2int($i) -> 41;
|
||||
char2int($j) -> 42;
|
||||
char2int($k) -> 43;
|
||||
char2int($m) -> 44;
|
||||
char2int($n) -> 45;
|
||||
char2int($o) -> 46;
|
||||
char2int($p) -> 47;
|
||||
char2int($q) -> 48;
|
||||
char2int($r) -> 49;
|
||||
char2int($s) -> 50;
|
||||
char2int($t) -> 51;
|
||||
char2int($u) -> 52;
|
||||
char2int($v) -> 53;
|
||||
char2int($w) -> 54;
|
||||
char2int($x) -> 55;
|
||||
char2int($y) -> 56;
|
||||
char2int($z) -> 57.
|
||||
298
snippets/vb64.erl
Normal file
298
snippets/vb64.erl
Normal file
@ -0,0 +1,298 @@
|
||||
-module(vb64).
|
||||
|
||||
-export([enc/1, dec/1]).
|
||||
|
||||
-export([test/0]).
|
||||
|
||||
test() ->
|
||||
test(100).
|
||||
|
||||
test(N) when N >= 0 ->
|
||||
RandBytes = rand:bytes(N),
|
||||
% encode the bytes
|
||||
CorrectEnc = erlang:binary_to_list(base64:encode(RandBytes)),
|
||||
MyEnc = enc(RandBytes),
|
||||
EncodeOk = CorrectEnc =:= MyEnc,
|
||||
% decode the bytes
|
||||
MyDec = dec(MyEnc),
|
||||
DecodeOk = MyDec =:= RandBytes,
|
||||
% print results if error
|
||||
ok =
|
||||
case EncodeOk of
|
||||
true ->
|
||||
ok;
|
||||
false ->
|
||||
ok = io:format("===~n"
|
||||
"Encode failure!~n"
|
||||
"input : ~tw~n"
|
||||
"expected output : ~tw~n"
|
||||
"actual output : ~tw~n"
|
||||
"===~n~n",
|
||||
[RandBytes, CorrectEnc, MyEnc]),
|
||||
ok
|
||||
end,
|
||||
ok =
|
||||
case DecodeOk of
|
||||
true ->
|
||||
ok;
|
||||
false ->
|
||||
ok = io:format("===~n"
|
||||
"Decode failure!~n"
|
||||
"input : ~tw~n"
|
||||
"expected output : ~tw~n"
|
||||
"actual output : ~tw~n"
|
||||
"===~n~n",
|
||||
[MyEnc, RandBytes, MyDec]),
|
||||
ok
|
||||
end,
|
||||
% recurse
|
||||
test(N - 1);
|
||||
test(_) ->
|
||||
ok.
|
||||
|
||||
|
||||
|
||||
-spec enc(Binary) -> Base64
|
||||
when Binary :: binary(),
|
||||
Base64 :: string().
|
||||
%% @doc
|
||||
%% "Encode" (from the perspective of the program) binary data into base64
|
||||
%% @end
|
||||
|
||||
|
||||
% general case: at least 3 bytes (24 bits = 6+6+6+6) remaining
|
||||
%
|
||||
% 12345678 abcdefgh 12345678 ...
|
||||
% 123456 78abcd efgh12 345678 ...
|
||||
% A B C D Rest
|
||||
% convert to chars ->
|
||||
% CA CB CC CD
|
||||
enc(<<A:6, B:6, C:6, D:6, Rest/binary>>) ->
|
||||
CA = int2char(A),
|
||||
CB = int2char(B),
|
||||
CC = int2char(C),
|
||||
CD = int2char(D),
|
||||
[CA, CB, CC, CD | enc(Rest)];
|
||||
% terminal case: 2 bytes (16 bits = 6+6+4) remaining
|
||||
%
|
||||
% 12345678 abcdefgh
|
||||
% 123456 78abcd efgh__
|
||||
% A B C bsl 2
|
||||
% convert to chars ->
|
||||
% CA CB CC =
|
||||
enc(<<A:6, B:6, C:4>>) ->
|
||||
CA = int2char(A),
|
||||
CB = int2char(B),
|
||||
CC = int2char(C bsl 2),
|
||||
[CA, CB, CC, $=];
|
||||
% terminal case: 1 byte (8 bits = 6+2) remaining
|
||||
%
|
||||
% 12345678 ->
|
||||
% 123456 78____
|
||||
% A B bsl 4
|
||||
% convert to chars ->
|
||||
% CA CB = =
|
||||
enc(<<A:6, B:2>>) ->
|
||||
CA = int2char(A),
|
||||
CB = int2char(B bsl 4),
|
||||
[CA, CB, $=, $=];
|
||||
% terminal case: 0 bytes remaining
|
||||
enc(<<>>) ->
|
||||
[].
|
||||
|
||||
|
||||
|
||||
-spec dec(Base64) -> Binary
|
||||
when Base64 :: string(),
|
||||
Binary :: binary().
|
||||
%% @doc
|
||||
%% "Decode" (from the perspective of the program) a Base64 string into binary data
|
||||
|
||||
dec(Base64_String) ->
|
||||
dec(Base64_String, <<>>).
|
||||
|
||||
|
||||
% terminal case: two equal signs at the end = 1 byte (8 bits = 6+2) remaining
|
||||
% input (characters) ->
|
||||
% W X = =
|
||||
% convert to numbers ->
|
||||
% abcdef gh____ = =
|
||||
% NW NX
|
||||
% regroup ->
|
||||
% abcdefgh ____ abcdef gh____
|
||||
% <<LastByte:8, 0:4>> = << NW:6, NX:6 >>
|
||||
dec([W, X, $=, $=], Acc) ->
|
||||
NW = char2int(W),
|
||||
NX = char2int(X),
|
||||
<<LastByte:8, 0:4>> = <<NW:6, NX:6>>,
|
||||
<<Acc/binary, LastByte:8>>;
|
||||
% terminal case: one equal sign at the end = 2 bytes remaining
|
||||
%
|
||||
% input (characters) ->
|
||||
% W X Y =
|
||||
% convert to numbers ->
|
||||
% abcdef gh1234 5678__ =
|
||||
% NW NX NY
|
||||
% regroup ->
|
||||
% abcdefgh 12345678 __ abcdef gh1234 5678__
|
||||
% << B1:8, B2:8, 0:2 >> = << NW:6, NX:6 NY:6 >>
|
||||
dec([W, X, Y, $=], Acc) ->
|
||||
NW = char2int(W),
|
||||
NX = char2int(X),
|
||||
NY = char2int(Y),
|
||||
<<B1:8, B2:8, 0:2>> = <<NW:6, NX:6, NY:6>>,
|
||||
<<Acc/binary, B1:8, B2:8>>;
|
||||
% terminal case: 0 bytes remaining
|
||||
% nothing to do
|
||||
dec([], Acc) ->
|
||||
Acc;
|
||||
% general case: no equal signs = 3 or more bytes remaining
|
||||
%
|
||||
% input (characters) ->
|
||||
% W X Y Z
|
||||
% convert to numbers ->
|
||||
% abcdef gh1234 5678ab cdefgh
|
||||
% NW NX NY NZ
|
||||
% decompose ->
|
||||
% abcdefgh 12345678 abcdefgh abcdef gh1234 5678ab cdefgh
|
||||
% << B1:8, B2:8, B3:2 >> = << NW:6, NX:6 NY:6, NZ:6 >>
|
||||
dec([W, X, Y, Z | Rest], Acc) ->
|
||||
NW = char2int(W),
|
||||
NX = char2int(X),
|
||||
NY = char2int(Y),
|
||||
NZ = char2int(Z),
|
||||
NewAcc = <<Acc/binary, NW:6, NX:6, NY:6, NZ:6>>,
|
||||
dec(Rest, NewAcc).
|
||||
|
||||
|
||||
|
||||
int2char( 0) -> $A;
|
||||
int2char( 1) -> $B;
|
||||
int2char( 2) -> $C;
|
||||
int2char( 3) -> $D;
|
||||
int2char( 4) -> $E;
|
||||
int2char( 5) -> $F;
|
||||
int2char( 6) -> $G;
|
||||
int2char( 7) -> $H;
|
||||
int2char( 8) -> $I;
|
||||
int2char( 9) -> $J;
|
||||
int2char(10) -> $K;
|
||||
int2char(11) -> $L;
|
||||
int2char(12) -> $M;
|
||||
int2char(13) -> $N;
|
||||
int2char(14) -> $O;
|
||||
int2char(15) -> $P;
|
||||
int2char(16) -> $Q;
|
||||
int2char(17) -> $R;
|
||||
int2char(18) -> $S;
|
||||
int2char(19) -> $T;
|
||||
int2char(20) -> $U;
|
||||
int2char(21) -> $V;
|
||||
int2char(22) -> $W;
|
||||
int2char(23) -> $X;
|
||||
int2char(24) -> $Y;
|
||||
int2char(25) -> $Z;
|
||||
int2char(26) -> $a;
|
||||
int2char(27) -> $b;
|
||||
int2char(28) -> $c;
|
||||
int2char(29) -> $d;
|
||||
int2char(30) -> $e;
|
||||
int2char(31) -> $f;
|
||||
int2char(32) -> $g;
|
||||
int2char(33) -> $h;
|
||||
int2char(34) -> $i;
|
||||
int2char(35) -> $j;
|
||||
int2char(36) -> $k;
|
||||
int2char(37) -> $l;
|
||||
int2char(38) -> $m;
|
||||
int2char(39) -> $n;
|
||||
int2char(40) -> $o;
|
||||
int2char(41) -> $p;
|
||||
int2char(42) -> $q;
|
||||
int2char(43) -> $r;
|
||||
int2char(44) -> $s;
|
||||
int2char(45) -> $t;
|
||||
int2char(46) -> $u;
|
||||
int2char(47) -> $v;
|
||||
int2char(48) -> $w;
|
||||
int2char(49) -> $x;
|
||||
int2char(50) -> $y;
|
||||
int2char(51) -> $z;
|
||||
int2char(52) -> $0;
|
||||
int2char(53) -> $1;
|
||||
int2char(54) -> $2;
|
||||
int2char(55) -> $3;
|
||||
int2char(56) -> $4;
|
||||
int2char(57) -> $5;
|
||||
int2char(58) -> $6;
|
||||
int2char(59) -> $7;
|
||||
int2char(60) -> $8;
|
||||
int2char(61) -> $9;
|
||||
int2char(62) -> $+;
|
||||
int2char(63) -> $/.
|
||||
|
||||
|
||||
char2int($A) -> 0;
|
||||
char2int($B) -> 1;
|
||||
char2int($C) -> 2;
|
||||
char2int($D) -> 3;
|
||||
char2int($E) -> 4;
|
||||
char2int($F) -> 5;
|
||||
char2int($G) -> 6;
|
||||
char2int($H) -> 7;
|
||||
char2int($I) -> 8;
|
||||
char2int($J) -> 9;
|
||||
char2int($K) -> 10;
|
||||
char2int($L) -> 11;
|
||||
char2int($M) -> 12;
|
||||
char2int($N) -> 13;
|
||||
char2int($O) -> 14;
|
||||
char2int($P) -> 15;
|
||||
char2int($Q) -> 16;
|
||||
char2int($R) -> 17;
|
||||
char2int($S) -> 18;
|
||||
char2int($T) -> 19;
|
||||
char2int($U) -> 20;
|
||||
char2int($V) -> 21;
|
||||
char2int($W) -> 22;
|
||||
char2int($X) -> 23;
|
||||
char2int($Y) -> 24;
|
||||
char2int($Z) -> 25;
|
||||
char2int($a) -> 26;
|
||||
char2int($b) -> 27;
|
||||
char2int($c) -> 28;
|
||||
char2int($d) -> 29;
|
||||
char2int($e) -> 30;
|
||||
char2int($f) -> 31;
|
||||
char2int($g) -> 32;
|
||||
char2int($h) -> 33;
|
||||
char2int($i) -> 34;
|
||||
char2int($j) -> 35;
|
||||
char2int($k) -> 36;
|
||||
char2int($l) -> 37;
|
||||
char2int($m) -> 38;
|
||||
char2int($n) -> 39;
|
||||
char2int($o) -> 40;
|
||||
char2int($p) -> 41;
|
||||
char2int($q) -> 42;
|
||||
char2int($r) -> 43;
|
||||
char2int($s) -> 44;
|
||||
char2int($t) -> 45;
|
||||
char2int($u) -> 46;
|
||||
char2int($v) -> 47;
|
||||
char2int($w) -> 48;
|
||||
char2int($x) -> 49;
|
||||
char2int($y) -> 50;
|
||||
char2int($z) -> 51;
|
||||
char2int($0) -> 52;
|
||||
char2int($1) -> 53;
|
||||
char2int($2) -> 54;
|
||||
char2int($3) -> 55;
|
||||
char2int($4) -> 56;
|
||||
char2int($5) -> 57;
|
||||
char2int($6) -> 58;
|
||||
char2int($7) -> 59;
|
||||
char2int($8) -> 60;
|
||||
char2int($9) -> 61;
|
||||
char2int($+) -> 62;
|
||||
char2int($/) -> 63.
|
||||
Loading…
x
Reference in New Issue
Block a user