Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
75 lines (62 sloc) 2.23 KB
-module(say_command_parser).
-export([to_redis/1, from_redis/1]).
%% Parse a string to be sent to redis
to_redis(ok) -> <<"+OK\r\n">>;
to_redis(nil) -> <<"$-1\r\n">>;
to_redis({error, Msg}) -> list_to_binary(["-ERR ", Msg, "\r\n"]);
to_redis([]) -> <<"">>;
to_redis(Msg) -> parse_to_redis(Msg).
parse_to_redis(Msg) -> list_to_binary(format_entry(Msg)).
parse_to_redis([], Data) -> Data;
parse_to_redis([H|T], Data) -> parse_to_redis(T, [Data, format_entry(H)]).
format_entry(E) when is_list(E)->
[
<<"*">>,
entry_length(E),
<<"\r\n">>,
parse_to_redis(E, [])
];
format_entry(E)->
[
<<"$">>,
entry_length(E),
<<"\r\n">>,
entry_value(E),
<<"\r\n">>
].
entry_value(E) when is_atom(E) -> atom_to_binary(E, utf8);
entry_value(E) when is_integer(E) -> integer_to_binary(E);
entry_value(E) when is_list(E) -> list_to_binary(E);
entry_value(E) when is_binary(E) -> E.
entry_length(E) when is_atom(E) -> entry_length(atom_to_list(E));
entry_length(E) when is_binary(E) -> entry_length(binary_to_list(E));
entry_length(E) when is_integer(E) -> <<"1">>;
entry_length(E) when is_list(E) -> integer_to_binary(length(E)).
%% Parse redis array to a string
from_redis(<<"+OK\r\n">>) -> ok;
from_redis(<<"$-1\r\n">>) -> nil;
from_redis(Msg) ->
SplittedMsg = binary:split(Msg, [<<"\r\n">>], [global,trim]),
parse_from_redis(SplittedMsg).
parse_from_redis(Data) -> parse_from_redis(Data, []).
parse_from_redis([], Data) -> Data;
parse_from_redis([<<"$", _/binary>>|T], Data) -> parse_from_redis(T, Data);
parse_from_redis([<<"*", I/binary>>|T], Data) ->
[Msg, E] = unnest_array(T, list_to_integer(binary_to_list(I))),
Entry = parse_from_redis(E),
case length(Data) of
0 -> parse_from_redis(Msg, Entry);
_ -> parse_from_redis(Msg, [Data, Entry])
end;
parse_from_redis([H|T], Data) ->
Entry = split_entry(H),
parse_from_redis(T, lists:append(Data, Entry)).
split_entry(E) -> binary:split(E, [<<" ">>], [global,trim]).
unnest_array(Msg, I) -> unnest_array(Msg, [], I).
unnest_array(Msg, Array, 0) -> [Msg, lists:reverse(Array)];
unnest_array([], Array, _) -> unnest_array([], Array, 0);
unnest_array([H|T], Array, I) ->
case H of
<<"$", _/binary>> -> unnest_array(T, [H|Array], I);
_ -> unnest_array(T, [H|Array], I-1)
end.