|
@@ -16,6 +16,8 @@
|
|
|
|
|
|
-export([init/0]).
|
|
|
-export([parse/2]).
|
|
|
+-export([events/1]).
|
|
|
+-export([event/1]).
|
|
|
|
|
|
-record(state, {
|
|
|
state_name = bom :: bom | events,
|
|
@@ -28,12 +30,21 @@
|
|
|
-type state() :: #state{}.
|
|
|
-export_type([state/0]).
|
|
|
|
|
|
--type event() :: #{
|
|
|
+-type parsed_event() :: #{
|
|
|
last_event_id := binary(),
|
|
|
event_type := binary(),
|
|
|
data := iolist()
|
|
|
}.
|
|
|
|
|
|
+-type event() :: #{
|
|
|
+ comment => iodata(),
|
|
|
+ data => iodata(),
|
|
|
+ event => iodata() | atom(),
|
|
|
+ id => iodata(),
|
|
|
+ retry => non_neg_integer()
|
|
|
+}.
|
|
|
+-export_type([event/0]).
|
|
|
+
|
|
|
-spec init() -> state().
|
|
|
init() ->
|
|
|
#state{}.
|
|
@@ -41,7 +52,7 @@ init() ->
|
|
|
%% @todo Add a function to retrieve the retry value from the state.
|
|
|
|
|
|
-spec parse(binary(), state())
|
|
|
- -> {event, event(), State} | {more, State}.
|
|
|
+ -> {event, parsed_event(), State} | {more, State}.
|
|
|
parse(Data0, State=#state{state_name=bom, buffer=Buffer}) ->
|
|
|
Data1 = case Buffer of
|
|
|
<<>> -> Data0;
|
|
@@ -220,3 +231,71 @@ parse_split_event_test() ->
|
|
|
ok.
|
|
|
|
|
|
-endif.
|
|
|
+
|
|
|
+-spec events([event()]) -> iolist().
|
|
|
+events(Events) ->
|
|
|
+ [event(Event) || Event <- Events].
|
|
|
+
|
|
|
+-spec event(event()) -> iolist().
|
|
|
+event(Event) ->
|
|
|
+ [
|
|
|
+ event_comment(Event),
|
|
|
+ event_id(Event),
|
|
|
+ event_name(Event),
|
|
|
+ event_data(Event),
|
|
|
+ event_retry(Event),
|
|
|
+ $\n
|
|
|
+ ].
|
|
|
+
|
|
|
+event_comment(#{comment := Comment}) ->
|
|
|
+ prefix_lines(Comment, <<>>);
|
|
|
+event_comment(_) ->
|
|
|
+ [].
|
|
|
+
|
|
|
+event_id(#{id := ID}) ->
|
|
|
+ nomatch = binary:match(iolist_to_binary(ID), <<"\n">>),
|
|
|
+ [<<"id: ">>, ID, $\n];
|
|
|
+event_id(_) ->
|
|
|
+ [].
|
|
|
+
|
|
|
+event_name(#{event := Name0}) ->
|
|
|
+ Name = if
|
|
|
+ is_atom(Name0) -> atom_to_binary(Name0, utf8);
|
|
|
+ true -> iolist_to_binary(Name0)
|
|
|
+ end,
|
|
|
+ nomatch = binary:match(Name, <<"\n">>),
|
|
|
+ [<<"event: ">>, Name, $\n];
|
|
|
+event_name(_) ->
|
|
|
+ [].
|
|
|
+
|
|
|
+event_data(#{data := Data}) ->
|
|
|
+ prefix_lines(Data, <<"data">>);
|
|
|
+event_data(_) ->
|
|
|
+ [].
|
|
|
+
|
|
|
+event_retry(#{retry := Retry}) ->
|
|
|
+ [<<"retry: ">>, integer_to_binary(Retry), $\n];
|
|
|
+event_retry(_) ->
|
|
|
+ [].
|
|
|
+
|
|
|
+prefix_lines(IoData, Prefix) ->
|
|
|
+ Lines = binary:split(iolist_to_binary(IoData), <<"\n">>, [global]),
|
|
|
+ [[Prefix, <<": ">>, Line, $\n] || Line <- Lines].
|
|
|
+
|
|
|
+-ifdef(TEST).
|
|
|
+event_test() ->
|
|
|
+ _ = event(#{}),
|
|
|
+ _ = event(#{comment => "test"}),
|
|
|
+ _ = event(#{data => "test"}),
|
|
|
+ _ = event(#{data => "test\ntest\ntest"}),
|
|
|
+ _ = event(#{data => "test\ntest\ntest\n"}),
|
|
|
+ _ = event(#{data => <<"test\ntest\ntest">>}),
|
|
|
+ _ = event(#{data => [<<"test">>, $\n, <<"test">>, [$\n, "test"]]}),
|
|
|
+ _ = event(#{event => test}),
|
|
|
+ _ = event(#{event => "test"}),
|
|
|
+ _ = event(#{id => "test"}),
|
|
|
+ _ = event(#{retry => 5000}),
|
|
|
+ _ = event(#{event => "test", data => "test"}),
|
|
|
+ _ = event(#{id => "test", event => "test", data => "test"}),
|
|
|
+ ok.
|
|
|
+-endif.
|