Browse Source

Add building of SSE events

Loïc Hoguin 6 years ago
parent
commit
93b2b897cd
1 changed files with 81 additions and 2 deletions
  1. 81 2
      src/cow_sse.erl

+ 81 - 2
src/cow_sse.erl

@@ -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.