From 93b2b897cde238506c803faad4d1602d79dba7c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Mon, 25 Jun 2018 15:26:58 +0200 Subject: Add building of SSE events --- src/cow_sse.erl | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/src/cow_sse.erl b/src/cow_sse.erl index dc195a1..9d4a91e 100644 --- a/src/cow_sse.erl +++ b/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. -- cgit v1.2.3