update ChangeLog
[lwes-erlang/github-mirror.git] / src / lwes_event.erl
blob8f62e88b994a57f456a5d3d5a629cb8c05269630
1 -module (lwes_event).
3 -include_lib ("lwes.hrl").
4 -include_lib ("lwes_internal.hrl").
6 %% API
7 -export([new/1,
8 set_uint16/3,
9 set_int16/3,
10 set_uint32/3,
11 set_int32/3,
12 set_uint64/3,
13 set_int64/3,
14 set_string/3,
15 set_ip_addr/3,
16 set_boolean/3,
17 set_byte/3,
18 set_float/3,
19 set_double/3,
20 set_long_string/3,
21 set_uint16_array/3,
22 set_int16_array/3,
23 set_uint32_array/3,
24 set_int32_array/3,
25 set_uint64_array/3,
26 set_int64_array/3,
27 set_string_array/3,
28 set_ip_addr_array/3,
29 set_boolean_array/3,
30 set_byte_array/3,
31 set_float_array/3,
32 set_double_array/3,
33 set_nuint16_array/3,
34 set_nint16_array/3,
35 set_nuint32_array/3,
36 set_nint32_array/3,
37 set_nuint64_array/3,
38 set_nint64_array/3,
39 set_nstring_array/3,
40 set_nboolean_array/3,
41 set_nbyte_array/3,
42 set_nfloat_array/3,
43 set_ndouble_array/3,
44 to_binary/1,
45 to_iolist/1,
46 from_udp_packet/2,
47 from_binary/1,
48 from_binary/2,
49 peek_name_from_udp/1,
50 header_fields_to_iolist/3,
51 has_header_fields/1,
52 from_json/1,
53 to_json/1,
54 to_json/2,
55 remove_attr/2
56 ]).
58 -define (write_nullable_array (LwesType,Guard,BinarySize,BinaryType, V ),
59 Len = length (V),
60 {Bitset, Data} = lists:foldl (
61 fun
62 (undefined, {BitAccum, DataAccum}) -> {<<0:1, BitAccum/bitstring>>, DataAccum};
63 (X, {BitAccum, DataAccum}) when Guard (X) ->
64 {<<1:1, BitAccum/bitstring>>, <<DataAccum/binary, X:BinarySize/BinaryType>>};
65 (_, _) -> erlang:error (badarg)
66 end, {<<>>, <<>>}, V),
67 LwesBitsetBin = lwes_bitset_rep (Len, Bitset),
68 <<LwesType:8/integer-unsigned-big,
69 Len:16/integer-unsigned-big, Len:16/integer-unsigned-big,
70 LwesBitsetBin/binary, Data/binary>>
73 -define (read_nullable_array (Bin, LwesType, ElementSize),
74 <<AL:16/integer-unsigned-big, _:16, Rest/binary>> = Bin,
75 {NotNullCount, BitsetLength, Bitset} = decode_bitset(AL, Rest),
76 Count = NotNullCount * ElementSize,
77 <<_:BitsetLength, Values:Count/bits, Rest2/binary>> = Rest,
78 { read_n_array (LwesType, AL, 1, Bitset ,Values, []), Rest2 }).
80 %%====================================================================
81 %% API
82 %%====================================================================
83 new (Name) when is_atom (Name) ->
84 new (atom_to_list (Name));
85 new (Name) ->
86 % assume the user will be setting values with calls below, so set attrs
87 % to an empty list
88 #lwes_event { name = Name, attrs = [] }.
90 set_int16 (E = #lwes_event { attrs = A }, K, V) when ?is_int16 (V) ->
91 E#lwes_event { attrs = [ { ?LWES_INT_16, K, V } | A ] };
92 set_int16 (_,_,_) ->
93 erlang:error(badarg).
94 set_uint16 (E = #lwes_event { attrs = A }, K, V) when ?is_uint16 (V) ->
95 E#lwes_event { attrs = [ { ?LWES_U_INT_16, K, V } | A ] };
96 set_uint16 (_,_,_) ->
97 erlang:error(badarg).
98 set_int32 (E = #lwes_event { attrs = A}, K, V) when ?is_int32 (V) ->
99 E#lwes_event { attrs = [ { ?LWES_INT_32, K, V } | A ] };
100 set_int32 (_,_,_) ->
101 erlang:error(badarg).
102 set_uint32 (E = #lwes_event { attrs = A}, K, V) when ?is_uint32 (V) ->
103 E#lwes_event { attrs = [ { ?LWES_U_INT_32, K, V } | A ] };
104 set_uint32 (_,_,_) ->
105 erlang:error(badarg).
106 set_int64 (E = #lwes_event { attrs = A}, K, V) when ?is_int64 (V) ->
107 E#lwes_event { attrs = [ { ?LWES_INT_64, K, V } | A ] };
108 set_int64 (_,_,_) ->
109 erlang:error(badarg).
110 set_uint64 (E = #lwes_event { attrs = A}, K, V) when ?is_uint64 (V) ->
111 E#lwes_event { attrs = [ { ?LWES_U_INT_64, K, V } | A ] };
112 set_uint64 (_,_,_) ->
113 erlang:error(badarg).
114 set_boolean (E = #lwes_event { attrs = A}, K, V) when is_boolean (V) ->
115 E#lwes_event { attrs = [ { ?LWES_BOOLEAN, K, V } | A ] };
116 set_boolean (_,_,_) ->
117 erlang:error(badarg).
118 set_string (E = #lwes_event { attrs = A}, K, V) when ?is_string (V) ->
119 E#lwes_event { attrs = [ { ?LWES_STRING, K, V } | A ] };
120 set_string (_,_,_) ->
121 erlang:error(badarg).
122 set_ip_addr (E = #lwes_event { attrs = A}, K, V) ->
123 Ip = lwes_util:normalize_ip (V),
124 E#lwes_event { attrs = [ { ?LWES_IP_ADDR, K, Ip } | A ] }.
125 % NOTE: no badarg case for set_ip_addr, as lwes_util:normalize_ip/1
126 % will throw badarg if there is an issue
127 set_byte(E = #lwes_event { attrs = A}, K, V) when ?is_byte (V) ->
128 E#lwes_event { attrs = [ { ?LWES_BYTE, K, V } | A ] };
129 set_byte(_,_,_) ->
130 erlang:error(badarg).
131 set_float(E = #lwes_event { attrs = A}, K, V) when is_float (V) ->
132 E#lwes_event { attrs = [ { ?LWES_FLOAT, K, V } | A ] };
133 set_float(_,_,_) ->
134 erlang:error(badarg).
135 set_double(E = #lwes_event { attrs = A}, K, V) when is_float (V) ->
136 E#lwes_event { attrs = [ { ?LWES_DOUBLE, K, V } | A ] };
137 set_double(_,_,_) ->
138 erlang:error(badarg).
139 set_long_string(E = #lwes_event { attrs = A}, K, V) when is_binary (V) ->
140 E#lwes_event { attrs = [ { ?LWES_LONG_STRING, K, V } | A ] };
141 set_long_string(_,_,_) ->
142 erlang:error(badarg).
143 set_uint16_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
144 E#lwes_event { attrs = [ { ?LWES_U_INT_16_ARRAY, K, V } | A ] };
145 set_uint16_array(_,_,_) ->
146 erlang:error(badarg).
147 set_int16_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
148 E#lwes_event { attrs = [ { ?LWES_INT_16_ARRAY, K, V } | A ] };
149 set_int16_array(_,_,_) ->
150 erlang:error(badarg).
151 set_uint32_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
152 E#lwes_event { attrs = [ { ?LWES_U_INT_32_ARRAY, K, V } | A ] };
153 set_uint32_array(_,_,_) ->
154 erlang:error(badarg).
155 set_int32_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
156 E#lwes_event { attrs = [ { ?LWES_INT_32_ARRAY, K, V } | A ] };
157 set_int32_array(_,_,_) ->
158 erlang:error(badarg).
159 set_uint64_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
160 E#lwes_event { attrs = [ { ?LWES_U_INT_64_ARRAY, K, V } | A ] };
161 set_uint64_array(_,_,_) ->
162 erlang:error(badarg).
163 set_int64_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
164 E#lwes_event { attrs = [ { ?LWES_INT_64_ARRAY, K, V } | A ] };
165 set_int64_array(_,_,_) ->
166 erlang:error(badarg).
167 set_string_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
168 E#lwes_event { attrs = [ { ?LWES_STRING_ARRAY, K, V } | A ] };
169 set_string_array(_,_,_) ->
170 erlang:error(badarg).
171 set_ip_addr_array (E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
172 Ips = [lwes_util:normalize_ip (I) || I <- V],
173 E#lwes_event { attrs = [ { ?LWES_IP_ADDR_ARRAY, K, Ips } | A ] };
174 set_ip_addr_array(_,_,_) ->
175 erlang:error(badarg).
176 set_boolean_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
177 E#lwes_event { attrs = [ { ?LWES_BOOLEAN_ARRAY, K, V } | A ] };
178 set_boolean_array(_,_,_) ->
179 erlang:error(badarg).
180 set_byte_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
181 E#lwes_event { attrs = [ { ?LWES_BYTE_ARRAY, K, V } | A ] };
182 set_byte_array(_,_,_) ->
183 erlang:error(badarg).
184 set_float_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
185 E#lwes_event { attrs = [ { ?LWES_FLOAT_ARRAY, K, V } | A ] };
186 set_float_array(_,_,_) ->
187 erlang:error(badarg).
188 set_double_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
189 E#lwes_event { attrs = [ { ?LWES_DOUBLE_ARRAY, K, V } | A ] };
190 set_double_array(_,_,_) ->
191 erlang:error(badarg).
192 set_nuint16_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
193 E#lwes_event { attrs = [ { ?LWES_N_U_INT_16_ARRAY, K, V } | A ] };
194 set_nuint16_array(_,_,_) ->
195 erlang:error(badarg).
196 set_nint16_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
197 E#lwes_event { attrs = [ { ?LWES_N_INT_16_ARRAY, K, V } | A ] };
198 set_nint16_array(_,_,_) ->
199 erlang:error(badarg).
200 set_nuint32_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
201 E#lwes_event { attrs = [ { ?LWES_N_U_INT_32_ARRAY, K, V } | A ] };
202 set_nuint32_array(_,_,_) ->
203 erlang:error(badarg).
204 set_nint32_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
205 E#lwes_event { attrs = [ { ?LWES_N_INT_32_ARRAY, K, V } | A ] };
206 set_nint32_array(_,_,_) ->
207 erlang:error(badarg).
208 set_nuint64_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
209 E#lwes_event { attrs = [ { ?LWES_N_U_INT_64_ARRAY, K, V } | A ] };
210 set_nuint64_array(_,_,_) ->
211 erlang:error(badarg).
212 set_nint64_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
213 E#lwes_event { attrs = [ { ?LWES_N_INT_64_ARRAY, K, V } | A ] };
214 set_nint64_array(_,_,_) ->
215 erlang:error(badarg).
216 set_nstring_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
217 E#lwes_event { attrs = [ { ?LWES_N_STRING_ARRAY, K, V } | A ] };
218 set_nstring_array(_,_,_) ->
219 erlang:error(badarg).
220 set_nboolean_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
221 E#lwes_event { attrs = [ { ?LWES_N_BOOLEAN_ARRAY, K, V } | A ] };
222 set_nboolean_array(_,_,_) ->
223 erlang:error(badarg).
224 set_nbyte_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
225 E#lwes_event { attrs = [ { ?LWES_N_BYTE_ARRAY, K, V } | A ] };
226 set_nbyte_array(_,_,_) ->
227 erlang:error(badarg).
228 set_nfloat_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
229 E#lwes_event { attrs = [ { ?LWES_N_FLOAT_ARRAY, K, V } | A ] };
230 set_nfloat_array(_,_,_) ->
231 erlang:error(badarg).
232 set_ndouble_array(E = #lwes_event { attrs = A}, K, V) when is_list (V) ->
233 E#lwes_event { attrs = [ { ?LWES_N_DOUBLE_ARRAY, K, V } | A ] };
234 set_ndouble_array(_,_,_) ->
235 erlang:error(badarg).
237 to_binary (Event = #lwes_event { }) ->
238 iolist_to_binary (to_iolist (Event));
239 % allow for re-emission of events, if it doesn't match the record, it
240 % could be a binary or an iolist, so just forward it through
241 to_binary (Event) ->
242 Event.
244 to_iolist (Event = #lwes_event { name = EventName, attrs = Attrs }) ->
245 case Attrs of
246 A when is_list(A) ->
247 NumAttrs = length (A),
248 [ write_name (EventName),
249 <<NumAttrs:16/integer-unsigned-big>>,
250 write_attrs (A, [])
252 Dict ->
253 to_iolist (Event#lwes_event { attrs = dict:to_list (Dict) })
254 end;
255 to_iolist (Event) ->
256 % assume if we get anything else it's either a binary or an iolist
257 Event.
259 peek_name_from_udp ({ udp, _, _, _, Packet }) ->
260 case read_name (Packet) of
261 { ok, EventName, _ } -> EventName;
262 E -> E
263 end.
265 header_fields_to_iolist (ReceiptTime, SenderIP, SenderPort) ->
266 % these need to be in reverse order as we don't bother reversing the io_list
267 write_attrs (
268 [ {?LWES_U_INT_16, <<"SenderPort">>, SenderPort},
269 {?LWES_IP_ADDR, <<"SenderIP">>, SenderIP},
270 {?LWES_INT_64, <<"ReceiptTime">>, ReceiptTime} ], []).
272 has_header_fields (B) when is_binary(B) ->
273 Size = erlang:byte_size (B),
274 % I need to check for the following at the end of the event binary
275 % int64 ReceiptTime = 1 (short string length)
276 % + 11 (length of string)
277 % + 1 (length of type byte)
278 % + 8 (length of int64)
279 % = 21
280 % ip_addr SenderIp = 1 + 8 + 1 + 4 = 14
281 % uint16 SenderPort = 1 + 10 + 1 + 2 = 14
283 % So total bytes at the end are 21+14+14 = 49
284 NumberToSkip = Size - 49,
286 case B of
287 <<_:NumberToSkip/bytes, % skip beginning
288 11:8/integer-unsigned-big, % length of "ReceiptTime" 11
289 "ReceiptTime", %
290 ?LWES_TYPE_INT_64:8/integer-unsigned-big, % type byte
291 _:64/integer-signed-big, % value
292 8:8/integer-unsigned-big, % length of "SenderIP" 8
293 "SenderIP", %
294 ?LWES_TYPE_IP_ADDR:8/integer-unsigned-big, % type byte
295 _:32/integer-unsigned-big, % value
296 10:8/integer-unsigned-big, % length of "SenderPort" 10
297 "SenderPort", %
298 ?LWES_TYPE_U_INT_16:8/integer-unsigned-big,% type byte
299 _:16/integer-unsigned-big>> -> % value
300 true;
301 _ ->
302 false
303 end.
305 from_udp_packet (Packet, raw) ->
306 Packet;
307 from_udp_packet ({ udp, Socket, SenderIP, SenderPort, Packet }, Format) ->
308 % allow ReceiptTime to come in via the second element of the tuple in
309 % some cases, this was put in place to work with the journal listener
310 ReceiptTime =
311 case Socket of
312 S when is_port(S) ->
313 millisecond_since_epoch();
314 R when is_integer(R) ->
316 end,
317 % only add header fields if they have not been added by upstream
318 Extra =
319 case has_header_fields (Packet) of
320 true -> [];
321 false ->
322 [ { ?LWES_IP_ADDR, <<"SenderIP">>, SenderIP },
323 { ?LWES_U_INT_16, <<"SenderPort">>, SenderPort },
324 { ?LWES_INT_64, <<"ReceiptTime">>, ReceiptTime } ]
325 end,
326 from_binary (Packet, Format, Extra).
328 from_binary (B) when is_binary (B) ->
329 from_binary (B, list).
331 from_binary (<<>>, _) ->
332 undefined;
333 from_binary (Binary, Format) ->
334 from_binary (Binary, Format, []).
336 %%====================================================================
337 %% Internal functions
338 %%====================================================================
339 from_binary (Binary, Format, Accum0) ->
340 { ok, EventName, Attrs } = read_name (Binary),
341 AttrList = read_attrs (Attrs, Accum0),
342 case is_json_format (Format) of
343 true ->
344 BinaryAttrList = normalize_to_binary (AttrList),
345 Jsoned = jsonify (BinaryAttrList),
346 EEP18Json =
347 case is_typed_json (Format) of
348 true ->
349 {[{<<"EventName">>, EventName},
350 { <<"typed">>,
351 { add_types (Jsoned) }
355 false ->
356 {[{<<"EventName">>, EventName} |
357 remove_types (Jsoned)
359 end,
360 eep18_convert_to (EEP18Json, json_format_to_structure (Format));
361 false ->
362 case Format of
363 list ->
364 #lwes_event { name = EventName,
365 attrs = remove_types (AttrList) };
366 dict ->
367 #lwes_event { name = EventName,
368 attrs = dict:from_list (remove_types(AttrList)) };
369 tagged ->
370 #lwes_event { name = EventName,
371 attrs = AttrList }
373 end.
375 normalize_to_binary (Attrs) ->
376 [ {T, K, make_binary(T, V)} || {T, K, V} <- Attrs ].
378 add_types (Attrs) ->
379 lists:foldl (
380 fun ({Type, Key, Value}, A) ->
381 [ { Key, {[{<<"type">>, Type},{<<"value">>, make_binary (Type, Value)}]} } | A ]
382 end,
384 Attrs).
386 remove_types (L) when is_list(L) ->
387 [ {K, V} || {_, K, V} <- L ].
389 jsonify (L) when is_list(L) ->
390 [ {Type, K, decode_json (Type, V) } || {Type, K, V} <- L ].
392 lwes_bitset_rep (Len, Bitset) ->
393 Padding = (erlang:byte_size(Bitset) * 8) - Len,
394 BitsetBin = <<0:Padding, Bitset/bitstring>>,
395 reverse_bytes_in_bin(BitsetBin).
397 reverse_bytes_in_bin (Bitset) ->
398 binary:list_to_bin(
399 lists:reverse(
400 binary:bin_to_list(Bitset))).
402 decode_bitset(AL, Bin) ->
403 BitsetLength = lwes_util:ceiling( AL/8 ) * 8,
404 <<Bitset:BitsetLength/bitstring, _/bitstring>> = Bin,
405 {lwes_util:count_ones(Bitset), BitsetLength, reverse_bytes_in_bin(Bitset)}.
407 type_to_atom (?LWES_TYPE_U_INT_16) -> ?LWES_U_INT_16;
408 type_to_atom (?LWES_TYPE_INT_16) -> ?LWES_INT_16;
409 type_to_atom (?LWES_TYPE_U_INT_32) -> ?LWES_U_INT_32;
410 type_to_atom (?LWES_TYPE_INT_32) -> ?LWES_INT_32;
411 type_to_atom (?LWES_TYPE_U_INT_64) -> ?LWES_U_INT_64;
412 type_to_atom (?LWES_TYPE_INT_64) -> ?LWES_INT_64;
413 type_to_atom (?LWES_TYPE_STRING) -> ?LWES_STRING;
414 type_to_atom (?LWES_TYPE_BOOLEAN) -> ?LWES_BOOLEAN;
415 type_to_atom (?LWES_TYPE_IP_ADDR) -> ?LWES_IP_ADDR;
416 type_to_atom (?LWES_TYPE_BYTE) -> ?LWES_BYTE;
417 type_to_atom (?LWES_TYPE_FLOAT) -> ?LWES_FLOAT;
418 type_to_atom (?LWES_TYPE_DOUBLE) -> ?LWES_DOUBLE;
419 type_to_atom (?LWES_TYPE_LONG_STRING) -> ?LWES_LONG_STRING;
420 type_to_atom (?LWES_TYPE_U_INT_16_ARRAY) -> ?LWES_U_INT_16_ARRAY;
421 type_to_atom (?LWES_TYPE_N_U_INT_16_ARRAY) -> ?LWES_N_U_INT_16_ARRAY;
422 type_to_atom (?LWES_TYPE_INT_16_ARRAY) -> ?LWES_INT_16_ARRAY;
423 type_to_atom (?LWES_TYPE_N_INT_16_ARRAY) -> ?LWES_N_INT_16_ARRAY;
424 type_to_atom (?LWES_TYPE_U_INT_32_ARRAY) -> ?LWES_U_INT_32_ARRAY;
425 type_to_atom (?LWES_TYPE_N_U_INT_32_ARRAY) -> ?LWES_N_U_INT_32_ARRAY;
426 type_to_atom (?LWES_TYPE_INT_32_ARRAY) -> ?LWES_INT_32_ARRAY;
427 type_to_atom (?LWES_TYPE_N_INT_32_ARRAY) -> ?LWES_N_INT_32_ARRAY;
428 type_to_atom (?LWES_TYPE_INT_64_ARRAY) -> ?LWES_INT_64_ARRAY;
429 type_to_atom (?LWES_TYPE_N_INT_64_ARRAY) -> ?LWES_N_INT_64_ARRAY;
430 type_to_atom (?LWES_TYPE_U_INT_64_ARRAY) -> ?LWES_U_INT_64_ARRAY;
431 type_to_atom (?LWES_TYPE_N_U_INT_64_ARRAY) -> ?LWES_N_U_INT_64_ARRAY;
432 type_to_atom (?LWES_TYPE_STRING_ARRAY) -> ?LWES_STRING_ARRAY;
433 type_to_atom (?LWES_TYPE_N_STRING_ARRAY) -> ?LWES_N_STRING_ARRAY;
434 type_to_atom (?LWES_TYPE_IP_ADDR_ARRAY) -> ?LWES_IP_ADDR_ARRAY;
435 type_to_atom (?LWES_TYPE_BOOLEAN_ARRAY) -> ?LWES_BOOLEAN_ARRAY;
436 type_to_atom (?LWES_TYPE_N_BOOLEAN_ARRAY) -> ?LWES_N_BOOLEAN_ARRAY;
437 type_to_atom (?LWES_TYPE_BYTE_ARRAY) -> ?LWES_BYTE_ARRAY;
438 type_to_atom (?LWES_TYPE_N_BYTE_ARRAY) -> ?LWES_N_BYTE_ARRAY;
439 type_to_atom (?LWES_TYPE_FLOAT_ARRAY) -> ?LWES_FLOAT_ARRAY;
440 type_to_atom (?LWES_TYPE_N_FLOAT_ARRAY) -> ?LWES_N_FLOAT_ARRAY;
441 type_to_atom (?LWES_TYPE_DOUBLE_ARRAY) -> ?LWES_DOUBLE_ARRAY;
442 type_to_atom (?LWES_TYPE_N_DOUBLE_ARRAY) -> ?LWES_N_DOUBLE_ARRAY.
444 millisecond_since_epoch () ->
445 {Meg, Sec, Mic} = os:timestamp(),
446 trunc (Meg * 1000000000 + Sec * 1000 + Mic / 1000).
448 write_sized (Min, Max, Thing) when is_atom (Thing) ->
449 write_sized (Min, Max, atom_to_list (Thing));
450 write_sized (Min, Max, Thing) ->
451 case iolist_size (Thing) of
452 L when L >= Min, L =< Max ->
453 [ <<L:8/integer-unsigned-big>>, Thing];
454 _ ->
455 throw (size_too_big)
456 end.
458 write_attrs ([], Accum) ->
459 Accum;
460 write_attrs ([{T,K,V} | Rest], Accum) ->
461 write_attrs (Rest, [ write_key (K), write (T, V) | Accum ]);
462 write_attrs ([{K,V} | Rest], Accum) ->
463 write_attrs (Rest, [ write_key (K), write (infer_type(V), V) | Accum ]).
466 % In the case where untyped values are being passed to lwes_event to
467 % encode, we will need to infer types from untyped values. In doing this
468 % integers will be packed into the smallest encoding type, so the first
469 % part of this functions breaks the integer ranges up according to
470 % the boundaries of the different types.
472 % Lists are then inspected and if the list is an iolist it will be treated
473 % as a string type, otherwise lists become lwes lists and can either be
474 % nullable if an undefined is found, or just a typed list if undefined
475 % is not found.
477 % Caveats:
478 % - using untyped lwes will result in more processing occuring as
479 % the entire structure must be scanned before a type is inferred.
480 % - string arrays are mostly indistinguishable from strings, with
481 % the exception of string arrays with atoms in them, so use the 3-tuple
482 % form if you want string arrays
483 % - byte arrays are indistinguishable from string, so use the 3-tuple
484 % form if you want byte arrays
485 % - all float types are assumed to be doubles
486 infer_type (V) when is_integer(V) ->
487 case V of
488 _ when V < -9223372036854775808 -> erlang:error(badarg);
489 _ when V >= -9223372036854775808, V < -2147483648 -> ?LWES_INT_64;
490 _ when V < -32768 -> ?LWES_INT_32;
491 _ when V < 0 -> ?LWES_INT_16;
492 _ when V =< 255 -> ?LWES_BYTE;
493 _ when V =< 32767 -> ?LWES_INT_16;
494 _ when V =< 65535 -> ?LWES_U_INT_16;
495 _ when V =< 2147483647 -> ?LWES_INT_32;
496 _ when V =< 4294967295 -> ?LWES_U_INT_32;
497 _ when V =< 9223372036854775807 -> ?LWES_INT_64;
498 _ when V =< 18446744073709551615 -> ?LWES_U_INT_64;
499 _ -> erlang:error(badarg)
500 end;
501 infer_type (V) when is_boolean(V) -> ?LWES_BOOLEAN;
502 infer_type (V) when ?is_ip_addr(V) -> ?LWES_IP_ADDR;
503 infer_type (V) when is_float(V) -> ?LWES_DOUBLE;
504 infer_type (V) when is_atom(V) -> ?LWES_STRING;
505 infer_type (V) when is_binary(V) ->
506 case iolist_size (V) of
507 SL when SL >= 0, SL =< 65535 -> ?LWES_STRING;
508 SL when SL=< 4294967295 -> ?LWES_LONG_STRING;
509 _ -> erlang:error(badarg)
510 end;
511 infer_type (V) when is_list(V) ->
512 case is_iolist(V) of
513 true ->
514 case iolist_size (V) of
515 SL when SL >= 0, SL =< 65535 -> ?LWES_STRING;
516 SL when SL=< 4294967295 -> ?LWES_LONG_STRING;
517 _ -> erlang:error(badarg)
518 end;
519 false -> infer_type(infer_array_type (V))
520 end;
521 infer_type ({undefined, ?LWES_U_INT_16}) -> ?LWES_U_INT_16_ARRAY;
522 infer_type ({undefined, ?LWES_INT_16}) -> ?LWES_INT_16_ARRAY;
523 infer_type ({undefined, ?LWES_U_INT_32}) -> ?LWES_U_INT_32_ARRAY;
524 infer_type ({undefined, ?LWES_INT_32}) -> ?LWES_INT_32_ARRAY;
525 infer_type ({undefined, ?LWES_U_INT_64}) -> ?LWES_U_INT_64_ARRAY;
526 infer_type ({undefined, ?LWES_INT_64}) -> ?LWES_INT_64_ARRAY;
527 infer_type ({undefined, ?LWES_STRING}) -> ?LWES_STRING_ARRAY;
528 infer_type ({undefined, ?LWES_BOOLEAN}) -> ?LWES_BOOLEAN_ARRAY;
529 infer_type ({undefined, ?LWES_IP_ADDR}) -> ?LWES_IP_ADDR_ARRAY;
530 % BYTE arrays can't actually be detected as they show up as strings
531 % infer_type ({undefined, ?LWES_BYTE}) -> ?LWES_BYTE_ARRAY;
532 % FLOAT arrays will be detected as doubles
533 % infer_type ({undefined, ?LWES_FLOAT}) -> ?LWES_FLOAT_ARRAY;
534 infer_type ({undefined, ?LWES_DOUBLE}) -> ?LWES_DOUBLE_ARRAY;
535 infer_type ({nullable, ?LWES_U_INT_16}) -> ?LWES_N_U_INT_16_ARRAY;
536 infer_type ({nullable, ?LWES_INT_16}) -> ?LWES_N_INT_16_ARRAY;
537 infer_type ({nullable, ?LWES_U_INT_32}) -> ?LWES_N_U_INT_32_ARRAY;
538 infer_type ({nullable, ?LWES_INT_32}) -> ?LWES_N_INT_32_ARRAY;
539 infer_type ({nullable, ?LWES_U_INT_64}) -> ?LWES_N_U_INT_64_ARRAY;
540 infer_type ({nullable, ?LWES_INT_64}) -> ?LWES_N_INT_64_ARRAY;
541 infer_type ({nullable, ?LWES_STRING}) -> ?LWES_N_STRING_ARRAY;
542 infer_type ({nullable, ?LWES_BOOLEAN}) -> ?LWES_N_BOOLEAN_ARRAY;
543 % currently UNIMPLEMENTED
544 % infer_type ({nullable, ?LWES_IP_ADDR}) -> ?LWES_N_IP_ADDR_ARRAY;
545 infer_type ({nullable, ?LWES_BYTE}) -> ?LWES_N_BYTE_ARRAY;
546 % FLOAT arrays will be detected as doubles
547 % infer_type ({nullable, ?LWES_FLOAT}) -> ?LWES_N_FLOAT_ARRAY;
548 infer_type ({nullable, ?LWES_DOUBLE}) -> ?LWES_N_DOUBLE_ARRAY;
549 infer_type (_) -> erlang:error(badarg).
551 infer_array_type (V)->
552 lists:foldr(fun infer_array_one/2, {undefined, undefined}, V).
554 infer_array_one (undefined, {_, Type}) -> {nullable, Type};
555 infer_array_one (T, {N, PrevType}) ->
556 NewType = infer_type (T),
557 {N, case is_integer(T) of
558 true ->
559 case int_order(NewType) > int_order(PrevType) of
560 true -> NewType;
561 false -> PrevType
562 end;
563 false ->
564 case PrevType of
565 _ when is_integer(PrevType)->
566 % can't mix integers and other types
567 erlang:error(badarg);
568 undefined -> NewType;
569 _ when PrevType =:= NewType -> NewType;
570 _ -> erlang:error(badarg)
575 int_order (?LWES_U_INT_64) -> 7;
576 int_order (?LWES_INT_64) -> 6;
577 int_order (?LWES_U_INT_32) -> 5;
578 int_order (?LWES_INT_32) -> 4;
579 int_order (?LWES_U_INT_16) -> 3;
580 int_order (?LWES_INT_16) -> 2;
581 int_order (?LWES_BYTE) -> 1;
582 int_order (undefined) -> 0.
584 % Found the basis of this function
585 % here http://erlang.org/pipermail/erlang-questions/2009-May/044073.html
586 % and modified to work, the types are here
587 % http://erlang.org/doc/reference_manual/typespec.html
588 % and state
590 % iodata() -> iolist() | binary()
591 % iolist() -> maybe_improper_list(byte() | binary() | iolist(), binary() | [])
593 is_iodata(B) when is_binary(B) -> true;
594 is_iodata(L) -> is_iolist(L).
596 is_iolist([]) -> true;
597 is_iolist([X|Xs]) when ?is_byte(X) ->
598 is_iodata(Xs);
599 is_iolist([X|Xs]) ->
600 case is_iodata(X) of
601 true -> is_iodata(Xs);
602 false -> false
603 end;
604 is_iolist(_) -> false.
606 write_key (Key) ->
607 write_sized (1, 255, Key).
609 write_name (Name) ->
610 write_sized (1, 127, Name).
612 write (?LWES_U_INT_16, V) ->
613 <<?LWES_TYPE_U_INT_16:8/integer-unsigned-big, V:16/integer-unsigned-big>>;
614 write (?LWES_INT_16, V) ->
615 <<?LWES_TYPE_INT_16:8/integer-unsigned-big, V:16/integer-signed-big>>;
616 write (?LWES_U_INT_32, V) ->
617 <<?LWES_TYPE_U_INT_32:8/integer-unsigned-big, V:32/integer-unsigned-big>>;
618 write (?LWES_INT_32, V) ->
619 <<?LWES_TYPE_INT_32:8/integer-unsigned-big, V:32/integer-signed-big>>;
620 write (?LWES_U_INT_64, V) ->
621 <<?LWES_TYPE_U_INT_64:8/integer-unsigned-big, V:64/integer-unsigned-big>>;
622 write (?LWES_INT_64, V) ->
623 <<?LWES_TYPE_INT_64:8/integer-unsigned-big, V:64/integer-signed-big>>;
624 write (?LWES_IP_ADDR, {V1, V2, V3, V4}) ->
625 <<?LWES_TYPE_IP_ADDR:8/integer-unsigned-big,
626 V4:8/integer-unsigned-big,
627 V3:8/integer-unsigned-big,
628 V2:8/integer-unsigned-big,
629 V1:8/integer-unsigned-big>>;
630 write (?LWES_BOOLEAN, true) ->
631 <<?LWES_TYPE_BOOLEAN:8/integer-unsigned-big, 1>>;
632 write (?LWES_BOOLEAN, false) ->
633 <<?LWES_TYPE_BOOLEAN:8/integer-unsigned-big, 0>>;
634 write (?LWES_STRING, V) when is_atom (V) ->
635 write (?LWES_STRING, atom_to_list (V));
636 write (?LWES_STRING, V) when is_list (V); is_binary (V) ->
637 write (?LWES_STRING, iolist_size (V), V);
638 write (?LWES_BYTE, V) ->
639 <<?LWES_TYPE_BYTE:8/integer-unsigned-big, V:8/integer-unsigned-big>>;
640 write (?LWES_FLOAT, V) ->
641 <<?LWES_TYPE_FLOAT:8/integer-unsigned-big, V:32/float>>;
642 write (?LWES_DOUBLE, V) ->
643 <<?LWES_TYPE_DOUBLE:8/integer-unsigned-big, V:64/float>>;
644 write (?LWES_LONG_STRING, V) when is_list(V); is_binary (V) ->
645 write (?LWES_LONG_STRING, iolist_size (V), V);
646 write (?LWES_U_INT_16_ARRAY, V) ->
647 Len = length (V),
648 V2 = lists:foldl (
650 (X, A) when ?is_uint16 (X) -> <<A/binary, X:16/integer-unsigned-big>>;
651 (_X, _A) -> erlang:error (badarg)
652 end, <<>>, V),
653 <<?LWES_TYPE_U_INT_16_ARRAY:8/integer-unsigned-big,
654 Len:16/integer-unsigned-big, V2/binary>>;
655 write (?LWES_INT_16_ARRAY, V) ->
656 Len = length (V),
657 V2 = lists:foldl (
659 (X, A) when ?is_int16 (X) -> <<A/binary, X:16/integer-signed-big>>;
660 (_, _) -> erlang:error (badarg)
661 end, <<>>, V),
662 <<?LWES_TYPE_INT_16_ARRAY:8/integer-unsigned-big,
663 Len:16/integer-unsigned-big, V2/binary>>;
664 write (?LWES_U_INT_32_ARRAY, V) ->
665 Len = length (V),
666 V2 = lists:foldl (
668 (X, A) when ?is_uint32 (X) -> <<A/binary, X:32/integer-unsigned-big>>;
669 (_, _) -> erlang:error (badarg)
670 end, <<>>, V),
671 <<?LWES_TYPE_U_INT_32_ARRAY:8/integer-unsigned-big,
672 Len:16/integer-unsigned-big, V2/binary>>;
673 write (?LWES_INT_32_ARRAY, V) ->
674 Len = length (V),
675 V2 = lists:foldl (
677 (X, A) when ?is_int32 (X) -> <<A/binary, X:32/integer-signed-big>>;
678 (_, _) -> erlang:error (badarg)
679 end, <<>>, V),
680 <<?LWES_TYPE_INT_32_ARRAY:8/integer-unsigned-big,
681 Len:16/integer-unsigned-big, V2/binary>>;
682 write (?LWES_U_INT_64_ARRAY, V) ->
683 Len = length (V),
684 V2 = lists:foldl (
686 (X, A) when ?is_uint64 (X) -> <<A/binary, X:64/integer-unsigned-big>>;
687 (_, _) -> erlang:error (badarg)
688 end, <<>>, V),
689 <<?LWES_TYPE_U_INT_64_ARRAY:8/integer-unsigned-big,
690 Len:16/integer-unsigned-big, V2/binary>>;
691 write (?LWES_INT_64_ARRAY, V) ->
692 Len = length (V),
693 V2 = lists:foldl (
695 (X, A) when ?is_int64 (X) -> <<A/binary, X:64/integer-signed-big>>;
696 (_, _) -> erlang:error (badarg)
697 end, <<>>, V),
698 <<?LWES_TYPE_INT_64_ARRAY:8/integer-unsigned-big,
699 Len:16/integer-unsigned-big, V2/binary>>;
700 write (?LWES_STRING_ARRAY, V) ->
701 Len = length (V),
702 V1 = string_array_to_binary (V),
703 V2 = lists:foldl (
704 fun(X, A) ->
705 case iolist_size (X) of
706 SL when SL >= 0, SL =< 65535 ->
707 <<A/binary, SL:16/integer-unsigned-big, X/binary>>;
708 _ ->
709 throw (string_too_big)
711 end, <<>>, V1),
712 <<?LWES_TYPE_STRING_ARRAY:8/integer-unsigned-big,
713 Len:16/integer-unsigned-big, V2/binary>>;
714 write (?LWES_IP_ADDR_ARRAY, V) ->
715 Len = length (V),
716 V2 = lists:foldl (
718 (X, A) when ?is_ip_addr (X) ->
719 {V1, V2, V3, V4} = X,
720 <<A/binary,
721 V4:8/integer-unsigned-big,
722 V3:8/integer-unsigned-big,
723 V2:8/integer-unsigned-big,
724 V1:8/integer-unsigned-big>>;
725 (_, _) -> erlang:error (badarg)
726 end, <<>>, V),
727 <<?LWES_TYPE_IP_ADDR_ARRAY:8/integer-unsigned-big,
728 Len:16/integer-unsigned-big, V2/binary>>;
729 write (?LWES_BOOLEAN_ARRAY, V) ->
730 Len = length (V),
731 V2 = lists:foldl (
733 (true, A) -> <<A/binary, 1>>;
734 (false, A) -> <<A/binary, 0>>;
735 (_, _) -> erlang:error (badarg)
736 end, <<>>, V),
737 <<?LWES_TYPE_BOOLEAN_ARRAY:8/integer-unsigned-big,
738 Len:16/integer-unsigned-big, V2/binary>>;
739 write (?LWES_BYTE_ARRAY, V) ->
740 Len = length (V),
741 V2 = lists:foldl (
743 (X, A) when ?is_byte (X) -> <<A/binary, X:8/integer-signed-big>>;
744 (_, _) -> erlang:error (badarg)
745 end, <<>>, V),
746 <<?LWES_TYPE_BYTE_ARRAY:8/integer-unsigned-big,
747 Len:16/integer-unsigned-big, V2/binary>>;
748 write (?LWES_FLOAT_ARRAY, V) ->
749 Len = length (V),
750 V2 = lists:foldl (
752 (X, A) when is_float (X) -> <<A/binary, X:32/float>>;
753 (_, _) -> erlang:error (badarg)
754 end, <<>>, V),
755 <<?LWES_TYPE_FLOAT_ARRAY:8/integer-unsigned-big,
756 Len:16/integer-unsigned-big, V2/binary>>;
757 write (?LWES_DOUBLE_ARRAY, V) ->
758 Len = length (V),
759 V2 = lists:foldl (
761 (X, A) when is_float (X) -> <<A/binary, X:64/float>>;
762 (_, _) -> erlang:error (badarg)
763 end, <<>>, V),
764 <<?LWES_TYPE_DOUBLE_ARRAY:8/integer-unsigned-big,
765 Len:16/integer-unsigned-big, V2/binary>>;
766 write (?LWES_N_U_INT_16_ARRAY, V) ->
767 ?write_nullable_array(?LWES_TYPE_N_U_INT_16_ARRAY,
768 ?is_uint16, 16, integer-unsigned-big, V);
769 write (?LWES_N_INT_16_ARRAY, V) ->
770 ?write_nullable_array(?LWES_TYPE_N_INT_16_ARRAY,
771 ?is_int16, 16, integer-signed-big, V);
772 write (?LWES_N_U_INT_32_ARRAY, V) ->
773 ?write_nullable_array(?LWES_TYPE_N_U_INT_32_ARRAY,
774 ?is_uint32, 32, integer-unsigned-big, V);
775 write (?LWES_N_INT_32_ARRAY, V) ->
776 ?write_nullable_array(?LWES_TYPE_N_INT_32_ARRAY,
777 ?is_int32, 32, integer-signed-big, V);
778 write (?LWES_N_U_INT_64_ARRAY, V) ->
779 ?write_nullable_array(?LWES_TYPE_N_U_INT_64_ARRAY,
780 ?is_uint64, 64, integer-unsigned-big, V);
781 write (?LWES_N_INT_64_ARRAY, V) ->
782 ?write_nullable_array(?LWES_TYPE_N_INT_64_ARRAY,
783 ?is_int64, 64, integer-signed-big, V);
784 write (?LWES_N_BYTE_ARRAY, V) ->
785 ?write_nullable_array(?LWES_TYPE_N_BYTE_ARRAY,
786 ?is_byte, 8, integer-signed-big, V);
787 write (?LWES_N_FLOAT_ARRAY, V) ->
788 ?write_nullable_array(?LWES_TYPE_N_FLOAT_ARRAY,
789 is_float, 32, float, V);
790 write (?LWES_N_DOUBLE_ARRAY, V) ->
791 ?write_nullable_array(?LWES_TYPE_N_DOUBLE_ARRAY,
792 is_float, 64, float, V);
793 write (?LWES_N_BOOLEAN_ARRAY, V) ->
794 Len = length (V),
795 {Bitset, Data} = lists:foldl (
797 (undefined, {BitAccum, DataAccum}) -> {<<0:1, BitAccum/bitstring>>, DataAccum};
798 (true, {BitAccum, DataAccum}) -> {<<1:1, BitAccum/bitstring>>, <<DataAccum/binary, 1>>};
799 (false,{BitAccum, DataAccum}) -> {<<1:1, BitAccum/bitstring>>, <<DataAccum/binary, 0>>};
800 (_, _) -> erlang:error (badarg)
801 end, {<<>>, <<>>}, V),
802 LwesBitsetBin = lwes_bitset_rep (Len, Bitset),
803 <<?LWES_TYPE_N_BOOLEAN_ARRAY:8/integer-unsigned-big,
804 Len:16/integer-unsigned-big, Len:16/integer-unsigned-big,
805 LwesBitsetBin/binary, Data/binary>>;
806 write (?LWES_N_STRING_ARRAY, V) ->
807 Len = length (V),
808 V1 = string_array_to_binary (V),
809 {Bitset, Data} = lists:foldl (
810 fun (undefined , {BitAccum, DataAccum}) -> {<<0:1, BitAccum/bitstring>>, DataAccum};
811 (X, {BitAccum, DataAccum}) ->
812 case iolist_size (X) of
813 SL when SL >= 0, SL =< 65535 ->
814 {<<1:1, BitAccum/bitstring>>,
815 <<DataAccum/binary, SL:16/integer-unsigned-big, X/binary>>};
816 _ ->
817 throw (string_too_big)
819 end, {<<>>,<<>>}, V1),
820 LwesBitsetBin = lwes_bitset_rep (Len, Bitset),
821 <<?LWES_TYPE_N_STRING_ARRAY:8/integer-unsigned-big,
822 Len:16/integer-unsigned-big, Len:16/integer-unsigned-big,
823 LwesBitsetBin/binary, Data/binary>>.
825 write (?LWES_STRING, Len, V) when is_list (V); is_binary (V) ->
826 case Len of
827 SL when SL >= 0, SL =< 65535 ->
828 [ <<?LWES_TYPE_STRING:8/integer-unsigned-big,
829 SL:16/integer-unsigned-big>>, V ];
830 _ ->
831 throw (string_too_big)
832 end;
833 write (?LWES_LONG_STRING, Len, V) when is_list(V); is_binary (V) ->
834 case Len of
835 SL when SL =< 4294967295
836 -> [ <<?LWES_TYPE_LONG_STRING:8/integer-unsigned-big,
837 SL:32/integer-unsigned-big>>, V ];
838 _ -> throw (string_too_big)
839 end.
841 read_name (<<Length:8/integer-unsigned-big,
842 EventName:Length/binary,
843 _NumAttrs:16/integer-unsigned-big,
844 Rest/binary>>) ->
845 { ok, EventName, Rest };
846 read_name (_) ->
847 { error, malformed_event }.
849 read_attrs (<<>>, Accum) ->
850 Accum;
851 read_attrs (Bin, Accum) ->
852 <<L:8/integer-unsigned-big, K:L/binary,
853 T:8/integer-unsigned-big, Vals/binary>> = Bin,
854 { V, Rest } = read_value (T, Vals),
855 read_attrs (Rest, [ {type_to_atom(T), K, V} | Accum ]).
857 read_value (?LWES_TYPE_U_INT_16, Bin) ->
858 <<V:16/integer-unsigned-big, Rest/binary>> = Bin,
859 { V, Rest };
860 read_value (?LWES_TYPE_INT_16, Bin) ->
861 <<V:16/integer-signed-big, Rest/binary>> = Bin,
862 { V, Rest };
863 read_value (?LWES_TYPE_U_INT_32, Bin) ->
864 <<V:32/integer-unsigned-big, Rest/binary>> = Bin,
865 { V, Rest };
866 read_value (?LWES_TYPE_INT_32, Bin) ->
867 <<V:32/integer-signed-big, Rest/binary>> = Bin,
868 { V, Rest };
869 read_value (?LWES_TYPE_U_INT_64, Bin) ->
870 <<V:64/integer-unsigned-big, Rest/binary>> = Bin,
871 { V, Rest };
872 read_value (?LWES_TYPE_INT_64, Bin) ->
873 <<V:64/integer-signed-big, Rest/binary>> = Bin,
874 { V, Rest };
875 read_value (?LWES_TYPE_IP_ADDR, Bin) ->
876 <<V1:8/integer-unsigned-big,
877 V2:8/integer-unsigned-big,
878 V3:8/integer-unsigned-big,
879 V4:8/integer-unsigned-big, Rest/binary>> = Bin,
880 { {V4, V3, V2, V1}, Rest };
881 read_value (?LWES_TYPE_BOOLEAN, Bin) ->
882 <<V:8/integer-unsigned-big, Rest/binary>> = Bin,
883 { case V of 0 -> false; _ -> true end, Rest };
884 read_value (?LWES_TYPE_STRING, Bin) ->
885 <<SL:16/integer-unsigned-big, V:SL/binary, Rest/binary>> = Bin,
886 { V, Rest };
887 read_value (?LWES_TYPE_BYTE, Bin) ->
888 <<V:8/integer-unsigned-big, Rest/binary>> = Bin,
889 { V, Rest };
890 read_value (?LWES_TYPE_FLOAT, Bin) ->
891 <<V:32/float, Rest/binary>> = Bin,
892 { V, Rest };
893 read_value (?LWES_TYPE_DOUBLE, Bin) ->
894 <<V:64/float, Rest/binary>> = Bin,
895 { V, Rest };
896 read_value (?LWES_TYPE_LONG_STRING, Bin) ->
897 <<BL:32/integer-unsigned-big, V:BL/binary, Rest/binary>> = Bin,
898 { V, Rest };
899 read_value (?LWES_TYPE_U_INT_16_ARRAY, Bin) ->
900 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
901 Count = AL*16,
902 <<Ints:Count/bits, Rest2/binary>> = Rest,
903 { read_array (?LWES_TYPE_U_INT_16, Ints, []), Rest2 };
904 read_value (?LWES_TYPE_INT_16_ARRAY, Bin) ->
905 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
906 Count = AL*16,
907 <<Ints:Count/bits, Rest2/binary>> = Rest,
908 { read_array (?LWES_TYPE_INT_16, Ints, []), Rest2 };
909 read_value (?LWES_TYPE_U_INT_32_ARRAY, Bin) ->
910 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
911 Count = AL*32,
912 <<Ints:Count/bits, Rest2/binary>> = Rest,
913 { read_array (?LWES_TYPE_U_INT_32, Ints, []), Rest2 };
914 read_value (?LWES_TYPE_INT_32_ARRAY, Bin) ->
915 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
916 Count = AL*32,
917 <<Ints:Count/bits, Rest2/binary>> = Rest,
918 { read_array (?LWES_TYPE_INT_32, Ints, []), Rest2 };
919 read_value (?LWES_TYPE_U_INT_64_ARRAY, Bin) ->
920 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
921 Count = AL*64,
922 <<Ints:Count/bits, Rest2/binary>> = Rest,
923 { read_array (?LWES_TYPE_U_INT_64, Ints, []), Rest2 };
924 read_value (?LWES_TYPE_INT_64_ARRAY, Bin) ->
925 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
926 Count = AL*64,
927 <<Ints:Count/bits, Rest2/binary>> = Rest,
928 { read_array (?LWES_TYPE_INT_64, Ints, []), Rest2 };
929 read_value (?LWES_TYPE_IP_ADDR_ARRAY, Bin) ->
930 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
931 Count = AL*4,
932 <<Ips:Count/binary, Rest2/binary>> = Rest,
933 { read_array (?LWES_TYPE_IP_ADDR, Ips, []), Rest2 };
934 read_value (?LWES_TYPE_BOOLEAN_ARRAY, Bin) ->
935 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
936 Count = AL*1,
937 <<Bools:Count/binary, Rest2/binary>> = Rest,
938 { read_array (?LWES_TYPE_BOOLEAN, Bools, []), Rest2 };
939 read_value (?LWES_TYPE_STRING_ARRAY, Bin) ->
940 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
941 read_string_array (AL, Rest, []);
942 read_value (?LWES_TYPE_BYTE_ARRAY, Bin) ->
943 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
944 <<Bytes:AL/binary, Rest2/binary>> = Rest,
945 { read_array (?LWES_TYPE_BYTE, Bytes, []), Rest2 };
946 read_value (?LWES_TYPE_FLOAT_ARRAY, Bin) ->
947 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
948 Count = AL*32,
949 <<Floats:Count/bits, Rest2/binary>> = Rest,
950 { read_array (?LWES_TYPE_FLOAT, Floats, []), Rest2 };
951 read_value (?LWES_TYPE_DOUBLE_ARRAY, Bin) ->
952 <<AL:16/integer-unsigned-big, Rest/binary>> = Bin,
953 Count = AL*64,
954 <<Doubles:Count/bits, Rest2/binary>> = Rest,
955 { read_array (?LWES_TYPE_DOUBLE, Doubles, []), Rest2 };
956 read_value (?LWES_TYPE_N_U_INT_16_ARRAY, Bin) ->
957 ?read_nullable_array(Bin, ?LWES_TYPE_U_INT_16, 16);
958 read_value (?LWES_TYPE_N_INT_16_ARRAY, Bin) ->
959 ?read_nullable_array(Bin, ?LWES_TYPE_INT_16, 16);
960 read_value (?LWES_TYPE_N_U_INT_32_ARRAY, Bin) ->
961 ?read_nullable_array(Bin, ?LWES_TYPE_U_INT_32, 32);
962 read_value (?LWES_TYPE_N_INT_32_ARRAY, Bin) ->
963 ?read_nullable_array(Bin, ?LWES_TYPE_INT_32, 32);
964 read_value (?LWES_TYPE_N_U_INT_64_ARRAY, Bin) ->
965 ?read_nullable_array(Bin, ?LWES_TYPE_U_INT_64, 64);
966 read_value (?LWES_TYPE_N_INT_64_ARRAY, Bin) ->
967 ?read_nullable_array(Bin, ?LWES_TYPE_INT_64, 64);
968 read_value (?LWES_TYPE_N_BOOLEAN_ARRAY, Bin) ->
969 ?read_nullable_array(Bin, ?LWES_TYPE_BOOLEAN, 8);
970 read_value (?LWES_TYPE_N_STRING_ARRAY, Bin) ->
971 <<AL:16/integer-unsigned-big, _:16, Rest/binary>> = Bin,
972 {_, Bitset_Length, Bitset} = decode_bitset(AL,Rest),
973 <<_:Bitset_Length, Rest2/binary>> = Rest,
974 read_n_string_array (AL, 1, Bitset, Rest2, []);
975 read_value (?LWES_TYPE_N_BYTE_ARRAY, Bin) ->
976 ?read_nullable_array(Bin, ?LWES_TYPE_BYTE, 8);
977 read_value (?LWES_TYPE_N_FLOAT_ARRAY, Bin) ->
978 ?read_nullable_array(Bin, ?LWES_TYPE_FLOAT, 32);
979 read_value (?LWES_TYPE_N_DOUBLE_ARRAY, Bin) ->
980 ?read_nullable_array(Bin, ?LWES_TYPE_DOUBLE, 64);
981 read_value (_, _) ->
982 throw (unknown_type).
985 %% ARRAY TYPE FUNCS
986 split_bounds(Index, Bitset) ->
987 Size = size(Bitset) * 8,
988 L = Size - Index,
989 R = Index - 1,
990 {L, R}.
992 read_array (_Type, <<>>, Acc) -> lists:reverse (Acc);
993 read_array (Type, Bin, Acc) ->
994 { V, Rest } = read_value (Type, Bin),
995 read_array (Type, Rest, [V] ++ Acc).
997 read_n_array (_Type, Count, Index, _Bitset, _Bin, Acc) when Index > Count ->
998 lists:reverse (Acc);
999 read_n_array (Type, Count, Index, Bitset, Bin, Acc) when Index =< Count ->
1000 {L, R} = split_bounds(Index, Bitset),
1001 << _:L/bits, X:1, _:R/bits >> = Bitset,
1002 { V, Rest } = case X of 0 -> {undefined, Bin};
1003 1 -> read_value (Type, Bin)
1004 end,
1005 read_n_array (Type, Count, Index + 1, Bitset, Rest, [V] ++ Acc).
1007 read_string_array (0, Bin, Acc) -> { lists:reverse (Acc), Bin };
1008 read_string_array (Count, Bin, Acc) ->
1009 { V, Rest } = read_value (?LWES_TYPE_STRING, Bin),
1010 read_string_array (Count-1, Rest, [V] ++ Acc).
1012 read_n_string_array (Count, Index, _Bitset, Bin, Acc) when Index > Count ->
1013 { lists:reverse (Acc), Bin };
1014 read_n_string_array (Count, Index, Bitset, Bin, Acc) when Index =< Count ->
1015 {L, R} = split_bounds(Index, Bitset),
1016 << _:L/bits, X:1, _:R/bits >> = Bitset,
1017 { V, Rest } = case X of 0 -> {undefined, Bin};
1018 1 -> read_value (?LWES_TYPE_STRING, Bin)
1019 end,
1020 read_n_string_array (Count, Index + 1,Bitset, Rest, [V] ++ Acc).
1022 string_array_to_binary (L) -> string_array_to_binary (L, []).
1023 string_array_to_binary ([], Acc) -> lists:reverse (Acc);
1024 string_array_to_binary ([ H | T ], Acc) when is_binary (H) ->
1025 string_array_to_binary (T, [H] ++ Acc);
1026 string_array_to_binary ([ H | T ], Acc) when is_list (H) ->
1027 string_array_to_binary (T, [list_to_binary (H)] ++ Acc);
1028 string_array_to_binary ([ H | T ], Acc) when is_atom (H) ->
1029 case H of
1030 undefined -> string_array_to_binary (T, [ undefined ] ++ Acc);
1031 _ -> string_array_to_binary (T,
1032 [ list_to_binary (atom_to_list (H)) ] ++ Acc)
1033 end;
1034 string_array_to_binary (_, _) ->
1035 erlang:error (badarg).
1037 to_json(Bin) when is_binary (Bin) ->
1038 from_binary(Bin, json_eep18_typed);
1039 to_json(Event= #lwes_event{name=_, attrs=_}) ->
1040 to_json(Event, json_eep18_typed).
1042 to_json (Bin, Format) when is_binary (Bin) ->
1043 from_binary (Bin, Format);
1044 to_json (Event, Format) ->
1045 from_binary (to_binary (Event), Format).
1047 from_json(Bin) when is_list(Bin); is_binary(Bin) ->
1048 from_json (lwes_mochijson2:decode (Bin, [{format, eep18}]));
1049 from_json ({Json}) ->
1050 Name = proplists:get_value (<<"EventName">>, Json),
1051 {TypedAttrs} = proplists:get_value (<<"typed">>, Json),
1052 #lwes_event {
1053 name = Name,
1054 attrs = lists:map (fun process_one/1, TypedAttrs)
1057 make_binary(Type, Value) ->
1058 case is_arr_type(Type) of
1059 true -> lwes_util:arr_to_binary(Value);
1060 false -> lwes_util:any_to_binary(Value)
1061 end.
1063 decode_json (Type, Value) ->
1064 Decoded =
1065 case is_arr_type (Type) of
1066 true ->
1067 [ decode_json_one (V) || V <- Value ];
1068 false ->
1069 decode_json_one (Value)
1070 end,
1071 Decoded.
1073 decode_json_one (Value) ->
1074 try lwes_mochijson2:decode (Value, [{format, eep18}]) of
1075 S -> S
1076 catch
1077 _:_ -> Value
1078 end.
1080 eep18_convert_to (Json, eep18) ->
1081 Json;
1082 eep18_convert_to (Json, struct) ->
1083 eep18_to_struct (Json);
1084 eep18_convert_to (Json, proplist) ->
1085 eep18_to_proplist (Json).
1087 eep18_to_struct ({L}) when is_list(L) ->
1088 {struct, eep18_to_struct(L)};
1089 eep18_to_struct (L) when is_list(L) ->
1090 [ eep18_to_struct (E) || E <- L ];
1091 eep18_to_struct ({K,V}) ->
1092 {K, eep18_to_struct (V)};
1093 eep18_to_struct (O) -> O.
1095 eep18_to_proplist ({L}) when is_list(L) ->
1096 eep18_to_proplist(L);
1097 eep18_to_proplist (L) when is_list(L) ->
1098 [ eep18_to_proplist (E) || E <- L ];
1099 eep18_to_proplist ({K,V}) ->
1100 {K, eep18_to_proplist (V)};
1101 eep18_to_proplist (O) -> O.
1104 process_one ({Key, {Attrs}}) ->
1105 Type = case proplists:get_value (<<"type">>, Attrs) of
1106 A when is_atom(A) -> A;
1107 B when is_binary(B) ->
1108 lwes_util:binary_to_any (B, atom)
1109 end,
1110 Value = proplists:get_value (<<"value">>, Attrs),
1111 NewValue =
1112 case Type of
1113 ?LWES_U_INT_16 -> lwes_util:binary_to_any (Value, integer);
1114 ?LWES_INT_16 -> lwes_util:binary_to_any (Value, integer);
1115 ?LWES_U_INT_32 -> lwes_util:binary_to_any (Value, integer);
1116 ?LWES_INT_32 -> lwes_util:binary_to_any (Value, integer);
1117 ?LWES_U_INT_64 -> lwes_util:binary_to_any (Value, integer);
1118 ?LWES_INT_64 -> lwes_util:binary_to_any (Value, integer);
1119 ?LWES_IP_ADDR -> lwes_util:binary_to_any (Value, ipaddr);
1120 ?LWES_BOOLEAN -> lwes_util:binary_to_any (Value, atom);
1121 ?LWES_STRING -> lwes_util:binary_to_any (Value, binary);
1122 ?LWES_BYTE -> lwes_util:binary_to_any (Value, integer);
1123 ?LWES_FLOAT -> lwes_util:binary_to_any (Value, float);
1124 ?LWES_DOUBLE -> lwes_util:binary_to_any (Value, float);
1125 ?LWES_U_INT_16_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1126 ?LWES_N_U_INT_16_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1127 ?LWES_INT_16_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1128 ?LWES_N_INT_16_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1129 ?LWES_U_INT_32_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1130 ?LWES_N_U_INT_32_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1131 ?LWES_INT_32_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1132 ?LWES_N_INT_32_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1133 ?LWES_INT_64_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1134 ?LWES_N_INT_64_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1135 ?LWES_U_INT_64_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1136 ?LWES_N_U_INT_64_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1137 ?LWES_STRING_ARRAY -> lwes_util:binary_to_arr (Value, binary);
1138 ?LWES_N_STRING_ARRAY -> lwes_util:binary_to_arr (Value, binary);
1139 ?LWES_IP_ADDR_ARRAY -> lwes_util:binary_to_arr (Value, ipaddr);
1140 ?LWES_BOOLEAN_ARRAY -> lwes_util:binary_to_arr (Value, atom);
1141 ?LWES_N_BOOLEAN_ARRAY -> lwes_util:binary_to_arr (Value, atom);
1142 ?LWES_BYTE_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1143 ?LWES_N_BYTE_ARRAY -> lwes_util:binary_to_arr (Value, integer);
1144 ?LWES_FLOAT_ARRAY -> lwes_util:binary_to_arr (Value, float);
1145 ?LWES_N_FLOAT_ARRAY -> lwes_util:binary_to_arr (Value, float);
1146 ?LWES_DOUBLE_ARRAY -> lwes_util:binary_to_arr (Value, float);
1147 ?LWES_N_DOUBLE_ARRAY -> lwes_util:binary_to_arr (Value, float)
1148 end,
1149 { Type, Key, NewValue }.
1151 is_json_format (json) -> true;
1152 is_json_format (json_untyped) -> true;
1153 is_json_format (json_typed) -> true;
1154 is_json_format (json_proplist) -> true;
1155 is_json_format (json_proplist_untyped) -> true;
1156 is_json_format (json_proplist_typed) -> true;
1157 is_json_format (json_eep18) -> true;
1158 is_json_format (json_eep18_untyped) -> true;
1159 is_json_format (json_eep18_typed) -> true;
1160 is_json_format (_) -> false.
1162 json_format_to_structure (json) -> struct;
1163 json_format_to_structure (json_untyped) -> struct;
1164 json_format_to_structure (json_typed) -> struct;
1165 json_format_to_structure (json_proplist) -> proplist;
1166 json_format_to_structure (json_proplist_untyped) -> proplist;
1167 json_format_to_structure (json_proplist_typed) -> proplist;
1168 json_format_to_structure (json_eep18) -> eep18;
1169 json_format_to_structure (json_eep18_untyped) -> eep18;
1170 json_format_to_structure (json_eep18_typed) -> eep18.
1172 is_typed_json (json_typed) -> true;
1173 is_typed_json (json_proplist_typed) -> true;
1174 is_typed_json (json_eep18_typed) -> true;
1175 is_typed_json (_) -> false.
1177 is_arr_type (?LWES_U_INT_16_ARRAY) -> true;
1178 is_arr_type (?LWES_N_U_INT_16_ARRAY) -> true;
1179 is_arr_type (?LWES_INT_16_ARRAY) -> true;
1180 is_arr_type (?LWES_N_INT_16_ARRAY) -> true;
1181 is_arr_type (?LWES_U_INT_32_ARRAY) -> true;
1182 is_arr_type (?LWES_N_U_INT_32_ARRAY) -> true;
1183 is_arr_type (?LWES_INT_32_ARRAY) -> true;
1184 is_arr_type (?LWES_N_INT_32_ARRAY) -> true;
1185 is_arr_type (?LWES_INT_64_ARRAY) -> true;
1186 is_arr_type (?LWES_N_INT_64_ARRAY) -> true;
1187 is_arr_type (?LWES_U_INT_64_ARRAY) -> true;
1188 is_arr_type (?LWES_N_U_INT_64_ARRAY) -> true;
1189 is_arr_type (?LWES_STRING_ARRAY) -> true;
1190 is_arr_type (?LWES_N_STRING_ARRAY) -> true;
1191 is_arr_type (?LWES_IP_ADDR_ARRAY) -> true;
1192 is_arr_type (?LWES_BOOLEAN_ARRAY) -> true;
1193 is_arr_type (?LWES_N_BOOLEAN_ARRAY) -> true;
1194 is_arr_type (?LWES_BYTE_ARRAY) -> true;
1195 is_arr_type (?LWES_N_BYTE_ARRAY) -> true;
1196 is_arr_type (?LWES_FLOAT_ARRAY) -> true;
1197 is_arr_type (?LWES_N_FLOAT_ARRAY) -> true;
1198 is_arr_type (?LWES_DOUBLE_ARRAY) -> true;
1199 is_arr_type (?LWES_N_DOUBLE_ARRAY) -> true;
1200 is_arr_type (_) -> false.
1202 %%====================================================================
1203 %% Test functions
1204 %%====================================================================
1205 remove_attr (A, #lwes_event { name = N, attrs = L }) ->
1206 #lwes_event { name = N, attrs = remove_attr (A, L) };
1207 remove_attr (A, {L}) when is_list (L) ->
1208 {remove_attr (A, L)};
1209 remove_attr (A, {struct, L}) when is_list (L) ->
1210 {struct, remove_attr (A, L)};
1211 remove_attr (A, L) when is_list (L) ->
1212 case lists:keyfind (<<"typed">>, 1, L) of
1213 false ->
1214 % for proplist style lists
1215 case lists:keydelete(A, 1, L) of
1216 L ->
1217 % for tagged style lists
1218 lists:keydelete(A, 2, L);
1219 L2 ->
1221 end;
1222 % deal with typed lists below
1223 {_, L2} when is_list(L2) ->
1224 lists:keyreplace (<<"typed">>,1,L,
1225 {<<"typed">>,
1226 lists:keydelete (A,1,L2)
1228 {_, {L2}} when is_list (L2) ->
1229 lists:keyreplace (<<"typed">>,1,L,
1230 {<<"typed">>,
1231 {lists:keydelete (A,1,L2)}
1233 {_,{struct,L3}} when is_list (L3) ->
1234 lists:keyreplace (<<"typed">>,1,L,
1235 {<<"typed">>,
1236 {struct, lists:keydelete (A,1,L3)}})
1237 end;
1238 remove_attr (A, D) ->
1239 dict:erase (A, D).
1242 -ifdef (TEST).
1243 -include_lib ("eunit/include/eunit.hrl").
1245 test_packet (binary) ->
1246 %% THIS IS A SERIALIZED PACKET
1247 %% SENT FROM THE JAVA LIBRARY
1248 %% THAT CONTAINS ALL TYPES
1249 %% captured from a java emitter at some point
1250 <<4,84,101,115,116,0,25,3,101,110,99,2,0,1,15,84,
1251 101,115,116,83,116,114,105,110,103,65,114,114,
1252 97,121,133,0,3,0,3,102,111,111,0,3,98,97,114,0,
1253 3,98,97,122,11,102,108,111,97,116,95,97,114,114,
1254 97,121,139,0,4,61,204,204,205,62,76,204,205,62,
1255 153,153,154,62,204,204,205,8,84,101,115,116,66,
1256 111,111,108,9,0,9,84,101,115,116,73,110,116,51,
1257 50,4,0,0,54,176,10,84,101,115,116,68,111,117,98,
1258 108,101,12,63,191,132,253,32,0,0,0,9,84,101,115,
1259 116,73,110,116,54,52,7,0,0,0,0,0,0,12,162,10,84,
1260 101,115,116,85,73,110,116,49,54,1,0,10,9,84,101,
1261 115,116,70,108,111,97,116,11,61,250,120,108,15,
1262 84,101,115,116,85,73,110,116,51,50,65,114,114,
1263 97,121,131,0,3,0,0,48,34,1,239,43,17,0,20,6,67,
1264 14,84,101,115,116,73,110,116,51,50,65,114,114,
1265 97,121,132,0,3,0,0,0,123,0,0,177,110,0,0,134,29,
1266 13,84,101,115,116,73,80,65,100,100,114,101,115,
1267 115,6,1,0,0,127,10,84,101,115,116,85,73,110,116,
1268 51,50,3,0,3,139,151,14,84,101,115,116,73,110,
1269 116,54,52,65,114,114,97,121,135,0,3,0,0,0,0,0,0,
1270 48,34,0,0,0,0,1,239,43,17,0,0,0,0,0,20,6,67,10,
1271 98,121,116,101,95,97,114,114,97,121,138,0,5,10,
1272 13,43,43,200,10,84,101,115,116,83,116,114,105,
1273 110,103,5,0,3,102,111,111,15,84,101,115,116,85,
1274 73,110,116,54,52,65,114,114,97,121,136,0,3,0,0,
1275 0,0,0,0,48,34,0,0,0,0,1,239,43,17,0,0,0,0,0,20,
1276 6,67,15,84,101,115,116,85,73,110,116,49,54,65,
1277 114,114,97,121,129,0,3,0,123,177,110,134,29,6,
1278 100,111,117,98,108,101,140,0,3,64,94,206,217,32,
1279 0,0,0,64,94,199,227,64,0,0,0,64,69,170,206,160,
1280 0,0,0,9,66,111,111,108,65,114,114,97,121,137,0,
1281 4,1,0,0,1,14,84,101,115,116,73,110,116,49,54,65,
1282 114,114,97,121,130,0,4,0,10,0,23,0,23,0,43,4,98,
1283 121,116,101,10,20,10,84,101,115,116,85,73,110,
1284 116,54,52,8,0,0,0,0,0,187,223,3,18,84,101,115,
1285 116,73,80,65,100,100,114,101,115,115,65,114,114,
1286 97,121,134,0,4,1,1,168,129,2,1,168,129,3,1,168,
1287 129,4,1,168,129,9,84,101,115,116,73,110,116,49,
1288 54,2,0,20>>;
1289 test_packet (raw) ->
1290 {udp,port, {192,168,54,1}, 58206, test_packet(binary)};
1291 test_packet (list) ->
1292 #lwes_event { name = <<"Test">>,
1293 attrs = [{<<"TestInt16">>,20},
1294 {<<"TestIPAddressArray">>,
1295 [{129,168,1,1},{129,168,1,2},
1296 {129,168,1,3},{129,168,1,4}]},
1297 {<<"TestUInt64">>,12312323},
1298 {<<"byte">>,20},
1299 {<<"TestInt16Array">>,[10,23,23,43]},
1300 {<<"BoolArray">>,[true,false,false,true]},
1301 {<<"double">>,
1302 [123.23200225830078,123.12324523925781,
1303 43.33443069458008]},
1304 {<<"TestUInt16Array">>,[123,45422,34333]},
1305 {<<"TestUInt64Array">>,[12322,32451345,1312323]},
1306 {<<"TestString">>,<<"foo">>},
1307 {<<"byte_array">>,[10,13,43,43,200]},
1308 {<<"TestInt64Array">>,[12322,32451345,1312323]},
1309 {<<"TestUInt32">>,232343},
1310 {<<"TestIPAddress">>,{127,0,0,1}},
1311 {<<"TestInt32Array">>,[123,45422,34333]},
1312 {<<"TestUInt32Array">>,[12322,32451345,1312323]},
1313 {<<"TestFloat">>,0.12229999899864197},
1314 {<<"TestUInt16">>,10},
1315 {<<"TestInt64">>,3234},
1316 {<<"TestDouble">>,0.12312299758195877},
1317 {<<"TestInt32">>,14000},
1318 {<<"TestBool">>,false},
1319 {<<"float_array">>,
1320 [0.10000000149011612,0.20000000298023224,
1321 0.30000001192092896, 0.4000000059604645]},
1322 {<<"TestStringArray">>,[<<"foo">>,<<"bar">>,<<"baz">>]},
1323 {<<"enc">>,1},
1324 {<<"SenderIP">>,{192,168,54,1}},
1325 {<<"SenderPort">>,58206},
1326 {<<"ReceiptTime">>,1439588532973}]
1328 test_packet (tagged) ->
1329 #lwes_event { name = <<"Test">>,
1330 attrs = [ {int16,<<"TestInt16">>,20},
1331 {ip_addr_array,<<"TestIPAddressArray">>,
1332 [{129,168,1,1}, {129,168,1,2}, {129,168,1,3},
1333 {129,168,1,4}]},
1334 {uint64,<<"TestUInt64">>,12312323},
1335 {byte,<<"byte">>,20},
1336 {int16_array,<<"TestInt16Array">>,[10,23,23,43]},
1337 {boolean_array,<<"BoolArray">>,
1338 [true,false,false,true]},
1339 {double_array,<<"double">>,
1340 [123.23200225830078,123.12324523925781,
1341 43.33443069458008]},
1342 {uint16_array,<<"TestUInt16Array">>,[123,45422,34333]},
1343 {uint64_array,<<"TestUInt64Array">>,[12322,32451345,1312323]},
1344 {string,<<"TestString">>,<<"foo">>},
1345 {byte_array,<<"byte_array">>,[10,13,43,43,200]},
1346 {int64_array,<<"TestInt64Array">>,[12322,32451345,1312323]},
1347 {uint32,<<"TestUInt32">>,232343},
1348 {ip_addr,<<"TestIPAddress">>,{127,0,0,1}},
1349 {int32_array,<<"TestInt32Array">>,[123,45422,34333]},
1350 {uint32_array,<<"TestUInt32Array">>,[12322,32451345,1312323]},
1351 {float,<<"TestFloat">>,0.12229999899864197},
1352 {uint16,<<"TestUInt16">>,10},
1353 {int64,<<"TestInt64">>,3234},
1354 {double,<<"TestDouble">>,0.12312299758195877},
1355 {int32,<<"TestInt32">>,14000},
1356 {boolean,<<"TestBool">>,false},
1357 {float_array,<<"float_array">>,
1358 [0.10000000149011612,0.20000000298023224,
1359 0.30000001192092896,0.4000000059604645]},
1360 {string_array,<<"TestStringArray">>,
1361 [<<"foo">>,<<"bar">>,<<"baz">>]},
1362 {int16,<<"enc">>,1},
1363 {ip_addr,<<"SenderIP">>,{192,168,54,1}},
1364 {uint16,<<"SenderPort">>,58206},
1365 {int64,<<"ReceiptTime">>,1439587738948}
1368 test_packet (dict) ->
1369 #lwes_event {
1370 name = <<"Test">>,
1371 attrs =
1372 {dict,28,16,16,8,80,48,
1373 {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]},
1374 {{[[<<"SenderPort">>|58206],
1375 [<<"ReceiptTime">>|1439588321444]],
1376 [[<<"TestDouble">>|0.12312299758195877],
1377 [<<"TestUInt32Array">>,12322,32451345,1312323]],
1379 [[<<"TestUInt16Array">>,123,45422,34333],
1380 [<<"TestInt16">>|20]],
1381 [[<<"TestBool">>|false],
1382 [<<"TestIPAddress">>|{127,0,0,1}],
1383 [<<"BoolArray">>,true,false,false,true],
1384 [<<"TestUInt64">>|12312323]],
1385 [[<<"enc">>|1],[<<"TestUInt32">>|232343]],
1386 [],[],
1387 [[<<"SenderIP">>|{192,168,54,1}],
1388 [<<"TestInt64Array">>,12322,32451345,1312323],
1389 [<<"TestIPAddressArray">>,
1390 {129,168,1,1},
1391 {129,168,1,2},
1392 {129,168,1,3},
1393 {129,168,1,4}]],
1394 [[<<"TestString">>|<<"foo">>]],
1396 [[<<"TestUInt16">>|10],
1397 [<<"TestFloat">>|0.12229999899864197],
1398 [<<"TestInt32Array">>,123,45422,34333]],
1399 [[<<"TestInt64">>|3234],
1400 [<<"byte_array">>,10,13,43,43,200],
1401 [<<"byte">>|20]],
1402 [[<<"TestStringArray">>,<<"foo">>,<<"bar">>,<<"baz">>],
1403 [<<"float_array">>,0.10000000149011612,
1404 0.20000000298023224,0.30000001192092896,
1405 0.4000000059604645],
1406 [<<"TestInt32">>|14000],
1407 [<<"TestInt16Array">>,10,23,23,43]],
1408 [[<<"TestUInt64Array">>,12322,32451345,1312323]],
1409 [[<<"double">>,123.23200225830078,123.12324523925781,
1410 43.33443069458008]]}}}
1412 test_packet (json) ->
1413 {struct,
1414 [ {<<"EventName">>,<<"Test">>},
1415 {<<"TestInt16">>,20},
1416 {<<"TestIPAddressArray">>,
1417 [<<"129.168.1.1">>, <<"129.168.1.2">>, <<"129.168.1.3">>,
1418 <<"129.168.1.4">>]},
1419 {<<"TestUInt64">>,12312323},
1420 {<<"byte">>,20},
1421 {<<"TestInt16Array">>,[10,23,23,43]},
1422 {<<"BoolArray">>,[true,false,false,true]},
1423 {<<"double">>,[123.23200225830078,123.12324523925781,43.33443069458008]},
1424 {<<"TestUInt16Array">>,[123,45422,34333]},
1425 {<<"TestUInt64Array">>,[12322,32451345,1312323]},
1426 {<<"TestString">>,<<"foo">>},
1427 {<<"byte_array">>,[10,13,43,43,200]},
1428 {<<"TestInt64Array">>,[12322,32451345,1312323]},
1429 {<<"TestUInt32">>,232343},
1430 {<<"TestIPAddress">>,<<"127.0.0.1">>},
1431 {<<"TestInt32Array">>,[123,45422,34333]},
1432 {<<"TestUInt32Array">>,[12322,32451345,1312323]},
1433 {<<"TestFloat">>,0.12229999899864197},
1434 {<<"TestUInt16">>,10},
1435 {<<"TestInt64">>,3234},
1436 {<<"TestDouble">>,0.12312299758195877},
1437 {<<"TestInt32">>,14000},
1438 {<<"TestBool">>,false},
1439 {<<"float_array">>,
1440 [0.10000000149011612,0.20000000298023224,0.30000001192092896,
1441 0.4000000059604645]},
1442 {<<"TestStringArray">>,[<<"foo">>,<<"bar">>,<<"baz">>]},
1443 {<<"enc">>,1},
1444 {<<"SenderIP">>,<<"192.168.54.1">>},
1445 {<<"SenderPort">>,58206},
1446 {<<"ReceiptTime">>,1439588435888}
1449 test_packet (json_untyped) ->
1450 test_packet (json);
1451 test_packet (json_typed) ->
1452 {struct,
1453 [{<<"EventName">>,<<"Test">>},
1454 {<<"typed">>,
1455 {struct,
1456 [{<<"ReceiptTime">>,
1457 {struct,[{<<"type">>,int64},{<<"value">>,<<"1439585933710">>}]}
1459 {<<"SenderPort">>,
1460 {struct,[{<<"type">>,uint16},{<<"value">>,<<"58206">>}]}
1462 {<<"SenderIP">>,
1463 {struct,[{<<"type">>,ip_addr},{<<"value">>,<<"192.168.54.1">>}]}
1465 {<<"enc">>,
1466 {struct,[{<<"type">>,int16},{<<"value">>,<<"1">>}]}
1468 {<<"TestStringArray">>,
1469 {struct,[{<<"type">>,string_array},
1470 {<<"value">>,[<<"foo">>,<<"bar">>,<<"baz">>]}]}
1472 {<<"float_array">>,
1473 {struct,
1474 [{<<"type">>,float_array},
1475 {<<"value">>,
1476 [<<"1.00000001490116119385e-01">>,<<"2.00000002980232238770e-01">>,
1477 <<"3.00000011920928955078e-01">>,<<"4.00000005960464477539e-01">>]
1481 {<<"TestBool">>,
1482 {struct,[{<<"type">>,boolean},{<<"value">>,<<"false">>}]}
1484 {<<"TestInt32">>,
1485 {struct,[{<<"type">>,int32},{<<"value">>,<<"14000">>}]}
1487 {<<"TestDouble">>,
1488 {struct,[{<<"type">>,double},
1489 {<<"value">>,<<"1.23122997581958770752e-01">>}]}
1491 {<<"TestInt64">>,
1492 {struct,[{<<"type">>,int64},{<<"value">>,<<"3234">>}]}
1494 {<<"TestUInt16">>,
1495 {struct,[{<<"type">>,uint16},{<<"value">>,<<"10">>}]}},
1496 {<<"TestFloat">>,
1497 {struct,[{<<"type">>,float},
1498 {<<"value">>,<<"1.22299998998641967773e-01">>}]}
1500 {<<"TestUInt32Array">>,
1501 {struct, [{<<"type">>,uint32_array},
1502 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]}
1504 {<<"TestInt32Array">>,
1505 {struct, [{<<"type">>,int32_array},
1506 {<<"value">>,[<<"123">>,<<"45422">>,<<"34333">>]}]}
1508 {<<"TestIPAddress">>,
1509 {struct, [{<<"type">>,ip_addr},{<<"value">>,<<"127.0.0.1">>}]}
1511 {<<"TestUInt32">>,
1512 {struct, [{<<"type">>,uint32},{<<"value">>,<<"232343">>}]}
1514 {<<"TestInt64Array">>,
1515 {struct, [{<<"type">>,int64_array},
1516 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]}
1518 {<<"byte_array">>,
1519 {struct, [{<<"type">>,byte_array},
1520 {<<"value">>,[<<"10">>,<<"13">>,<<"43">>,
1521 <<"43">>,<<"200">>]}]}
1523 {<<"TestString">>,
1524 {struct,[{<<"type">>,string},{<<"value">>,<<"foo">>}]}
1526 {<<"TestUInt64Array">>,
1527 {struct,[{<<"type">>,uint64_array},
1528 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]}
1530 {<<"TestUInt16Array">>,
1531 {struct, [{<<"type">>,uint16_array},
1532 {<<"value">>,[<<"123">>,<<"45422">>,<<"34333">>]}]}
1534 {<<"double">>,
1535 {struct, [{<<"type">>,double_array},
1536 {<<"value">>,
1537 [<<"1.23232002258300781250e+02">>,
1538 <<"1.23123245239257812500e+02">>,
1539 <<"4.33344306945800781250e+01">>]}]}
1541 {<<"BoolArray">>,
1542 {struct, [{<<"type">>,boolean_array},
1543 {<<"value">>,[<<"true">>,<<"false">>,
1544 <<"false">>,<<"true">>]}]}
1546 {<<"TestInt16Array">>,
1547 {struct, [{<<"type">>,int16_array},
1548 {<<"value">>,[<<"10">>,<<"23">>,<<"23">>,<<"43">>]}]}
1550 {<<"byte">>,{struct, [{<<"type">>,byte},{<<"value">>,<<"20">>}]}},
1551 {<<"TestUInt64">>,
1552 {struct, [{<<"type">>,uint64},{<<"value">>,<<"12312323">>}]}
1554 {<<"TestIPAddressArray">>,
1555 {struct, [{<<"type">>,ip_addr_array},
1556 {<<"value">>,
1557 [<<"129.168.1.1">>,<<"129.168.1.2">>,<<"129.168.1.3">>,
1558 <<"129.168.1.4">>]}]}
1560 {<<"TestInt16">>,
1561 {struct, [{<<"type">>,int16},{<<"value">>,<<"20">>}]}}
1567 test_packet (json_proplist) ->
1568 [ {<<"EventName">>,<<"Test">>},
1569 {<<"TestInt16">>,20},
1570 {<<"TestIPAddressArray">>,
1571 [<<"129.168.1.1">>, <<"129.168.1.2">>, <<"129.168.1.3">>,
1572 <<"129.168.1.4">>]},
1573 {<<"TestUInt64">>,12312323},
1574 {<<"byte">>,20},
1575 {<<"TestInt16Array">>,[10,23,23,43]},
1576 {<<"BoolArray">>,[true,false,false,true]},
1577 {<<"double">>,[123.23200225830078,123.12324523925781,43.33443069458008]},
1578 {<<"TestUInt16Array">>,[123,45422,34333]},
1579 {<<"TestUInt64Array">>,[12322,32451345,1312323]},
1580 {<<"TestString">>,<<"foo">>},
1581 {<<"byte_array">>,[10,13,43,43,200]},
1582 {<<"TestInt64Array">>,[12322,32451345,1312323]},
1583 {<<"TestUInt32">>,232343},
1584 {<<"TestIPAddress">>,<<"127.0.0.1">>},
1585 {<<"TestInt32Array">>,[123,45422,34333]},
1586 {<<"TestUInt32Array">>,[12322,32451345,1312323]},
1587 {<<"TestFloat">>,0.12229999899864197},
1588 {<<"TestUInt16">>,10},
1589 {<<"TestInt64">>,3234},
1590 {<<"TestDouble">>,0.12312299758195877},
1591 {<<"TestInt32">>,14000},
1592 {<<"TestBool">>,false},
1593 {<<"float_array">>,
1594 [0.10000000149011612,0.20000000298023224,0.30000001192092896,
1595 0.4000000059604645]},
1596 {<<"TestStringArray">>,[<<"foo">>,<<"bar">>,<<"baz">>]},
1597 {<<"enc">>,1},
1598 {<<"SenderIP">>,<<"192.168.54.1">>},
1599 {<<"SenderPort">>,58206},
1600 {<<"ReceiptTime">>,1439588435888}
1602 test_packet (json_proplist_untyped) ->
1603 test_packet (json_proplist);
1604 test_packet (json_proplist_typed) ->
1605 [{<<"EventName">>,<<"Test">>},
1606 {<<"typed">>,
1607 [{<<"ReceiptTime">>,[{<<"type">>,int64},{<<"value">>,<<"1439585933710">>}]},
1608 {<<"SenderPort">>,[{<<"type">>,uint16},{<<"value">>,<<"58206">>}]},
1609 {<<"SenderIP">>,[{<<"type">>,ip_addr},{<<"value">>,<<"192.168.54.1">>}]},
1610 {<<"enc">>,[{<<"type">>,int16},{<<"value">>,<<"1">>}]},
1611 {<<"TestStringArray">>,
1612 [{<<"type">>,string_array},
1613 {<<"value">>,[<<"foo">>,<<"bar">>,<<"baz">>]}]},
1614 {<<"float_array">>,
1615 [{<<"type">>,float_array},
1616 {<<"value">>,
1617 [<<"1.00000001490116119385e-01">>,<<"2.00000002980232238770e-01">>,
1618 <<"3.00000011920928955078e-01">>,<<"4.00000005960464477539e-01">>]}]
1620 {<<"TestBool">>,[{<<"type">>,boolean},{<<"value">>,<<"false">>}]},
1621 {<<"TestInt32">>,[{<<"type">>,int32},{<<"value">>,<<"14000">>}]},
1622 {<<"TestDouble">>,
1623 [{<<"type">>,double},{<<"value">>,<<"1.23122997581958770752e-01">>}]},
1624 {<<"TestInt64">>,[{<<"type">>,int64},{<<"value">>,<<"3234">>}]},
1625 {<<"TestUInt16">>,[{<<"type">>,uint16},{<<"value">>,<<"10">>}]},
1626 {<<"TestFloat">>,
1627 [{<<"type">>,float},{<<"value">>,<<"1.22299998998641967773e-01">>}]},
1628 {<<"TestUInt32Array">>,
1629 [{<<"type">>,uint32_array},
1630 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]},
1631 {<<"TestInt32Array">>,
1632 [{<<"type">>,int32_array},
1633 {<<"value">>,[<<"123">>,<<"45422">>,<<"34333">>]}]},
1634 {<<"TestIPAddress">>,[{<<"type">>,ip_addr},{<<"value">>,<<"127.0.0.1">>}]},
1635 {<<"TestUInt32">>,[{<<"type">>,uint32},{<<"value">>,<<"232343">>}]},
1636 {<<"TestInt64Array">>,
1637 [{<<"type">>,int64_array},
1638 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]},
1639 {<<"byte_array">>,
1640 [{<<"type">>,byte_array},
1641 {<<"value">>,[<<"10">>,<<"13">>,<<"43">>,<<"43">>,<<"200">>]}]},
1642 {<<"TestString">>,[{<<"type">>,string},{<<"value">>,<<"foo">>}]},
1643 {<<"TestUInt64Array">>,
1644 [{<<"type">>,uint64_array},
1645 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]},
1646 {<<"TestUInt16Array">>,
1647 [{<<"type">>,uint16_array},
1648 {<<"value">>,[<<"123">>,<<"45422">>,<<"34333">>]}]},
1649 {<<"double">>,
1650 [{<<"type">>,double_array},
1651 {<<"value">>,
1652 [<<"1.23232002258300781250e+02">>,<<"1.23123245239257812500e+02">>,
1653 <<"4.33344306945800781250e+01">>]}]},
1654 {<<"BoolArray">>,
1655 [{<<"type">>,boolean_array},
1656 {<<"value">>,[<<"true">>,<<"false">>,<<"false">>,<<"true">>]}]},
1657 {<<"TestInt16Array">>,
1658 [{<<"type">>,int16_array},
1659 {<<"value">>,[<<"10">>,<<"23">>,<<"23">>,<<"43">>]}]},
1660 {<<"byte">>,[{<<"type">>,byte},{<<"value">>,<<"20">>}]},
1661 {<<"TestUInt64">>,[{<<"type">>,uint64},{<<"value">>,<<"12312323">>}]},
1662 {<<"TestIPAddressArray">>,
1663 [{<<"type">>,ip_addr_array},
1664 {<<"value">>,
1665 [<<"129.168.1.1">>,<<"129.168.1.2">>,<<"129.168.1.3">>,
1666 <<"129.168.1.4">>]}]},
1667 {<<"TestInt16">>,[{<<"type">>,int16},{<<"value">>,<<"20">>}]}]
1670 test_packet (json_eep18) ->
1671 {test_packet (json_proplist)};
1672 test_packet (json_eep18_untyped) ->
1673 test_packet (json_eep18);
1674 test_packet (json_eep18_typed) ->
1675 {[{<<"EventName">>,<<"Test">>},
1676 {<<"typed">>,
1677 {[{ <<"ReceiptTime">>,
1678 {[{<<"type">>,int64},{<<"value">>,<<"1439592736063">>}]}
1680 { <<"SenderPort">>,
1681 {[{<<"type">>,uint16},{<<"value">>,<<"58206">>}]}
1683 { <<"SenderIP">>,
1684 {[{<<"type">>,ip_addr},{<<"value">>,<<"192.168.54.1">>}]}
1686 {<<"enc">>,{[{<<"type">>,int16},{<<"value">>,<<"1">>}]}},
1687 {<<"TestStringArray">>,
1688 {[{<<"type">>,string_array},
1689 {<<"value">>,[<<"foo">>,<<"bar">>,<<"baz">>]}]}
1691 {<<"float_array">>,
1692 {[{<<"type">>,float_array},
1693 {<<"value">>,
1694 [<<"1.00000001490116119385e-01">>,<<"2.00000002980232238770e-01">>,
1695 <<"3.00000011920928955078e-01">>,<<"4.00000005960464477539e-01">>]
1699 {<<"TestBool">>,{[{<<"type">>,boolean},{<<"value">>,<<"false">>}]}},
1700 {<<"TestInt32">>,{[{<<"type">>,int32},{<<"value">>,<<"14000">>}]}},
1701 {<<"TestDouble">>,
1702 {[{<<"type">>,double},{<<"value">>,<<"1.23122997581958770752e-01">>}]}},
1703 {<<"TestInt64">>,{[{<<"type">>,int64},{<<"value">>,<<"3234">>}]}},
1704 {<<"TestUInt16">>,{[{<<"type">>,uint16},{<<"value">>,<<"10">>}]}},
1705 {<<"TestFloat">>,
1706 {[{<<"type">>,float},{<<"value">>,<<"1.22299998998641967773e-01">>}]}},
1707 {<<"TestUInt32Array">>,
1708 {[{<<"type">>,uint32_array},
1709 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]}
1711 {<<"TestInt32Array">>,
1712 {[{<<"type">>,int32_array},
1713 {<<"value">>,[<<"123">>,<<"45422">>,<<"34333">>]}]}},
1714 {<<"TestIPAddress">>,
1715 {[{<<"type">>,ip_addr},{<<"value">>,<<"127.0.0.1">>}]}},
1716 {<<"TestUInt32">>,{[{<<"type">>,uint32},{<<"value">>,<<"232343">>}]}},
1717 {<<"TestInt64Array">>,
1718 {[{<<"type">>,int64_array},
1719 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]}},
1720 {<<"byte_array">>,
1721 {[{<<"type">>,byte_array},
1722 {<<"value">>,[<<"10">>,<<"13">>,<<"43">>,<<"43">>,<<"200">>]}]}},
1723 {<<"TestString">>,{[{<<"type">>,string},{<<"value">>,<<"foo">>}]}},
1724 {<<"TestUInt64Array">>,
1725 {[{<<"type">>,uint64_array},
1726 {<<"value">>,[<<"12322">>,<<"32451345">>,<<"1312323">>]}]}},
1727 {<<"TestUInt16Array">>,
1728 {[{<<"type">>,uint16_array},
1729 {<<"value">>,[<<"123">>,<<"45422">>,<<"34333">>]}]}},
1730 {<<"double">>,
1731 {[{<<"type">>,double_array},
1732 {<<"value">>,
1733 [<<"1.23232002258300781250e+02">>,<<"1.23123245239257812500e+02">>,
1734 <<"4.33344306945800781250e+01">>]}]}},
1735 {<<"BoolArray">>,
1736 {[{<<"type">>,boolean_array},
1737 {<<"value">>,[<<"true">>,<<"false">>,<<"false">>,<<"true">>]}]}},
1738 {<<"TestInt16Array">>,
1739 {[{<<"type">>,int16_array},
1740 {<<"value">>,[<<"10">>,<<"23">>,<<"23">>,<<"43">>]}]}},
1741 {<<"byte">>,{[{<<"type">>,byte},{<<"value">>,<<"20">>}]}},
1742 {<<"TestUInt64">>,{[{<<"type">>,uint64},{<<"value">>,<<"12312323">>}]}},
1743 {<<"TestIPAddressArray">>,
1744 {[{<<"type">>,ip_addr_array},
1745 {<<"value">>,
1746 [<<"129.168.1.1">>,<<"129.168.1.2">>,<<"129.168.1.3">>,
1747 <<"129.168.1.4">>]}]}},
1748 {<<"TestInt16">>,{[{<<"type">>,int16},{<<"value">>,<<"20">>}]}}
1755 nested_event (event) ->
1756 #lwes_event {
1757 name = <<"test">>,
1758 attrs =
1759 [ {<<"foo">>,<<"{\"bar\":\"baz\",\"bob\":5,\"inner\":{\"a\":5,\"b\":[1,2,3],\"c\":\"another\"}}">>},
1760 {<<"other">>,<<"[1,2,3,4]">>},
1761 {<<"ip">>, {127,0,0,1}}
1764 nested_event (binary) ->
1765 <<4,116,101,115,116,0,3,2,105,112,6,1,0,0,127,5,111,116,104,101,114,5,
1766 0,9,91,49,44,50,44,51,44,52,93,3,102,111,111,5,0,63,123,34,98,97,114,34,
1767 58,34,98,97,122,34,44,34,98,111,98,34,58,53,44,34,105,110,110,101,114,34,
1768 58,123,34,97,34,58,53,44,34,98,34,58,91,49,44,50,44,51,93,44,34,99,34,58,
1769 34,97,110,111,116,104,101,114,34,125,125>>;
1770 nested_event (json) ->
1771 {struct,[{<<"EventName">>,<<"test">>},
1772 {<<"foo">>,
1773 {struct,[{<<"bar">>,<<"baz">>},
1774 {<<"bob">>,5},
1775 {<<"inner">>, {struct,[{<<"a">>,5},
1776 {<<"b">>,[1,2,3]},
1777 {<<"c">>,<<"another">>}]
1783 {<<"other">>,[1,2,3,4]},
1784 {<<"ip">>,<<"127.0.0.1">>}
1787 nested_event (json_untyped) ->
1788 nested_event (json);
1789 nested_event (json_typed) ->
1790 {struct,
1791 [{<<"EventName">>,<<"test">>},
1792 {<<"typed">>,
1793 {struct,
1794 [{<<"ip">>,
1795 {struct,[{<<"type">>,ip_addr},{<<"value">>,<<"127.0.0.1">>}]}},
1796 {<<"other">>,
1797 {struct,[{<<"type">>,string},{<<"value">>,<<1,2,3,4>>}]}},
1798 {<<"foo">>,
1799 {struct,
1800 [{<<"type">>,string},
1801 {<<"value">>,
1802 {struct,
1803 [{<<"bar">>,<<"baz">>},
1804 {<<"bob">>,5},
1805 {<<"inner">>,
1806 {struct,
1807 [{<<"a">>,5},
1808 {<<"b">>,[1,2,3]},
1809 {<<"c">>,<<"another">>}]}}]}}]}}]}}]};
1810 nested_event (json_proplist) ->
1811 [{<<"EventName">>,<<"test">>},
1812 {<<"foo">>,
1813 [{<<"bar">>,<<"baz">>},
1814 {<<"bob">>,5},
1815 {<<"inner">>,
1816 [{<<"a">>,5},
1817 {<<"b">>,[1,2,3]},
1818 {<<"c">>,<<"another">>}
1823 {<<"other">>,[1,2,3,4]},
1824 {<<"ip">>,<<"127.0.0.1">>}
1826 nested_event (json_proplist_untyped) ->
1827 nested_event (json_proplist);
1828 nested_event (json_proplist_typed) ->
1829 [{<<"EventName">>,<<"test">>},
1830 {<<"typed">>,
1831 [{<<"ip">>,[{<<"type">>,ip_addr},{<<"value">>,<<"127.0.0.1">>}]},
1832 {<<"other">>,
1833 [{<<"type">>,string},{<<"value">>,<<1,2,3,4>>}]},
1834 {<<"foo">>,
1835 [{<<"type">>,string},
1836 {<<"value">>,
1837 [{<<"bar">>,<<"baz">>},
1838 {<<"bob">>,5},
1839 {<<"inner">>,
1840 [{<<"a">>,5},
1841 {<<"b">>,[1,2,3]},
1842 {<<"c">>,<<"another">>}]}]}]}]}];
1843 nested_event (json_eep18) ->
1844 {[{<<"EventName">>,<<"test">>},
1845 {<<"foo">>,
1846 {[{<<"bar">>,<<"baz">>},
1847 {<<"bob">>,5},
1848 {<<"inner">>,
1849 {[{<<"a">>,5},
1850 {<<"b">>,[1,2,3]},
1851 {<<"c">>,<<"another">>}]}}]}},
1852 {<<"other">>,[1,2,3,4]},
1853 {<<"ip">>,<<"127.0.0.1">>}]};
1854 nested_event (json_eep18_untyped) ->
1855 nested_event (json_eep18);
1856 nested_event (json_eep18_typed) ->
1857 {[{<<"EventName">>,<<"test">>},
1858 {<<"typed">>,
1859 {[{<<"ip">>,{[{<<"type">>,ip_addr},{<<"value">>,<<"127.0.0.1">>}]}},
1860 {<<"other">>,{[{<<"type">>,string},{<<"value">>,<<1,2,3,4>>}]}},
1861 {<<"foo">>,
1862 {[{<<"type">>,string},
1863 {<<"value">>,
1864 {[{<<"bar">>,<<"baz">>},
1865 {<<"bob">>,5},
1866 {<<"inner">>,
1867 {[{<<"a">>,5},
1868 {<<"b">>,[1,2,3]},
1869 {<<"c">>,<<"another">>}]}}]}}]}}]}}]}.
1871 test_text () ->
1872 <<"{\"EventName\":\"Test\",\"typed\":{\"SenderPort\":{\"type\":\"uint16\",\"value\":\"58206\"},\"SenderIP\":{\"type\":\"ip_addr\",\"value\":\"192.168.54.1\"},\"enc\":{\"type\":\"int16\",\"value\":\"1\"},\"TestStringArray\":{\"type\":\"string_array\",\"value\":[\"foo\",\"bar\",\"baz\"]},\"float_array\":{\"type\":\"float_array\",\"value\":[\"1.00000001490116119385e-01\",\"2.00000002980232238770e-01\",\"3.00000011920928955078e-01\",\"4.00000005960464477539e-01\"]},\"TestBool\":{\"type\":\"boolean\",\"value\":\"false\"},\"TestInt32\":{\"type\":\"int32\",\"value\":\"14000\"},\"TestDouble\":{\"type\":\"double\",\"value\":\"1.23122997581958770752e-01\"},\"TestInt64\":{\"type\":\"int64\",\"value\":\"3234\"},\"TestUInt16\":{\"type\":\"uint16\",\"value\":\"10\"},\"TestFloat\":{\"type\":\"float\",\"value\":\"1.22299998998641967773e-01\"},\"TestUInt32Array\":{\"type\":\"uint32_array\",\"value\":[\"12322\",\"32451345\",\"1312323\"]},\"TestInt32Array\":{\"type\":\"int32_array\",\"value\":[\"123\",\"45422\",\"34333\"]},\"TestIPAddress\":{\"type\":\"ip_addr\",\"value\":\"127.0.0.1\"},\"TestUInt32\":{\"type\":\"uint32\",\"value\":\"232343\"},\"TestInt64Array\":{\"type\":\"int64_array\",\"value\":[\"12322\",\"32451345\",\"1312323\"]},\"byte_array\":{\"type\":\"byte_array\",\"value\":[\"10\",\"13\",\"43\",\"43\",\"200\"]},\"TestString\":{\"type\":\"string\",\"value\":\"foo\"},\"TestUInt64Array\":{\"type\":\"uint64_array\",\"value\":[\"12322\",\"32451345\",\"1312323\"]},\"TestUInt16Array\":{\"type\":\"uint16_array\",\"value\":[\"123\",\"45422\",\"34333\"]},\"double\":{\"type\":\"double_array\",\"value\":[\"1.23232002258300781250e+02\",\"1.23123245239257812500e+02\",\"4.33344306945800781250e+01\"]},\"BoolArray\":{\"type\":\"boolean_array\",\"value\":[\"true\",\"false\",\"false\",\"true\"]},\"TestInt16Array\":{\"type\":\"int16_array\",\"value\":[\"10\",\"23\",\"23\",\"43\"]},\"byte\":{\"type\":\"byte\",\"value\":\"20\"},\"TestUInt64\":{\"type\":\"uint64\",\"value\":\"12312323\"},\"TestIPAddressArray\":{\"type\":\"ip_addr_array\",\"value\":[\"129.168.1.1\",\"129.168.1.2\",\"129.168.1.3\",\"129.168.1.4\"]},\"TestInt16\":{\"type\":\"int16\",\"value\":\"20\"}}}">>.
1875 json_formats () ->
1877 json, json_untyped, json_typed,
1878 json_proplist, json_proplist_untyped, json_proplist_typed,
1879 json_eep18, json_eep18_untyped, json_eep18_typed
1881 formats() -> [ list, tagged, dict | json_formats() ].
1884 functional_interface_test_ () ->
1886 ?_assertEqual (#lwes_event {name = "foo", attrs = []},
1887 new (foo)),
1888 % INT16 tests
1889 ?_assertEqual (#lwes_event{name = "foo",
1890 attrs = [{?LWES_INT_16,cat,0}]},
1891 set_int16 (new(foo),cat,0)),
1892 ?_assertEqual (#lwes_event{name = "foo",
1893 attrs = [{?LWES_INT_16,cat,-5}]},
1894 set_int16 (new(foo),cat,-5)),
1895 ?_assertEqual (#lwes_event{name = "foo",
1896 attrs = [{?LWES_INT_16,cat,50}]},
1897 set_int16 (new(foo),cat,50)),
1898 ?_assertEqual (#lwes_event{name = "foo",
1899 attrs = [{?LWES_INT_16_ARRAY,cat,
1900 [1,0,-1]}]},
1901 set_int16_array (new(foo),cat,[1,0,-1])),
1902 ?_assertError (badarg,
1903 set_int16_array (new(foo),cat,a)),
1904 ?_assertEqual (#lwes_event{name = "foo",
1905 attrs = [{?LWES_N_INT_16_ARRAY,cat,
1906 [1,0,undefined]}]},
1907 set_nint16_array (new(foo),cat,
1908 [1,0,undefined])),
1909 ?_assertError (badarg,
1910 set_nint16_array (new(foo),cat,a)),
1911 % INT16 bounds tests
1912 ?_assertError (badarg,
1913 set_int16 (new(foo),cat,32768)),
1914 ?_assertError (badarg,
1915 set_int16 (new(foo),cat,-32769)),
1917 % UINT16 tests
1918 ?_assertEqual (#lwes_event{name = "foo",
1919 attrs = [{?LWES_U_INT_16,cat,0}]},
1920 set_uint16 (new(foo),cat,0)),
1921 ?_assertEqual (#lwes_event{name = "foo",
1922 attrs = [{?LWES_U_INT_16,cat,5}]},
1923 set_uint16 (new(foo),cat,5)),
1924 ?_assertEqual (#lwes_event{name = "foo",
1925 attrs = [{?LWES_U_INT_16_ARRAY,cat,
1926 [1,0,1]}]},
1927 set_uint16_array (new(foo),cat,[1,0,1])),
1928 ?_assertError (badarg,
1929 set_uint16_array (new(foo),cat,a)),
1930 ?_assertEqual (#lwes_event{name = "foo",
1931 attrs = [{?LWES_N_U_INT_16_ARRAY,cat,
1932 [1,0,undefined]}]},
1933 set_nuint16_array (new(foo),cat,
1934 [1,0,undefined])),
1935 ?_assertError (badarg,
1936 set_nuint16_array (new(foo),cat,a)),
1937 % UINT16 bounds tests
1938 ?_assertError (badarg,
1939 set_uint16 (new(foo),cat,-5)),
1940 ?_assertError (badarg,
1941 set_uint16 (new(foo),cat,65536)),
1943 % INT32 tests
1944 ?_assertEqual (#lwes_event{name = "foo",
1945 attrs = [{?LWES_INT_32,cat,0}]},
1946 set_int32 (new(foo),cat,0)),
1947 ?_assertEqual (#lwes_event{name = "foo",
1948 attrs = [{?LWES_INT_32,cat,-5}]},
1949 set_int32 (new(foo),cat,-5)),
1950 ?_assertEqual (#lwes_event{name = "foo",
1951 attrs = [{?LWES_INT_32,cat,50}]},
1952 set_int32 (new(foo),cat,50)),
1953 ?_assertEqual (#lwes_event{name = "foo",
1954 attrs = [{?LWES_INT_32_ARRAY,cat,
1955 [1,0,-1]}]},
1956 set_int32_array (new(foo),cat,[1,0,-1])),
1957 ?_assertError (badarg,
1958 set_int32_array (new(foo),cat,a)),
1959 ?_assertEqual (#lwes_event{name = "foo",
1960 attrs = [{?LWES_N_INT_32_ARRAY,cat,
1961 [-1,0,undefined]}]},
1962 set_nint32_array (new(foo),cat,
1963 [-1,0,undefined])),
1964 ?_assertError (badarg,
1965 set_nint32_array (new(foo),cat,a)),
1966 % INT32 bounds tests
1967 ?_assertError (badarg,
1968 set_int32 (new(foo),cat,2147483648)),
1969 ?_assertError (badarg,
1970 set_int32 (new(foo),cat,-2147483649)),
1972 % UINT32 tests
1973 ?_assertEqual (#lwes_event{name = "foo",
1974 attrs = [{?LWES_U_INT_32,cat,0}]},
1975 set_uint32 (new(foo),cat,0)),
1976 ?_assertEqual (#lwes_event{name = "foo",
1977 attrs = [{?LWES_U_INT_32,cat,50}]},
1978 set_uint32 (new(foo),cat,50)),
1979 ?_assertEqual (#lwes_event{name = "foo",
1980 attrs = [{?LWES_U_INT_32,cat,4294967295}]},
1981 set_uint32 (new(foo),cat,4294967295)),
1982 ?_assertEqual (#lwes_event{name = "foo",
1983 attrs = [{?LWES_U_INT_32_ARRAY,cat,
1984 [1,0,1]}]},
1985 set_uint32_array (new(foo),cat,[1,0,1])),
1986 ?_assertError (badarg,
1987 set_uint32_array (new(foo),cat,a)),
1988 ?_assertEqual (#lwes_event{name = "foo",
1989 attrs = [{?LWES_N_U_INT_32_ARRAY,cat,
1990 [1,0,undefined]}]},
1991 set_nuint32_array (new(foo),cat,
1992 [1,0,undefined])),
1993 ?_assertError (badarg,
1994 set_nuint32_array (new(foo),cat,a)),
1996 % UINT32 bounds tests
1997 ?_assertError (badarg,
1998 set_uint32 (new(foo),cat,-5)),
1999 ?_assertError (badarg,
2000 set_uint32 (new(foo),cat,4294967296)),
2001 % INT64 tests
2002 ?_assertEqual (#lwes_event{name = "foo",
2003 attrs = [{?LWES_INT_64,cat,0}]},
2004 set_int64 (new(foo),cat,0)),
2005 ?_assertEqual (#lwes_event{name = "foo",
2006 attrs = [{?LWES_INT_64,cat,-5}]},
2007 set_int64 (new(foo),cat,-5)),
2008 ?_assertEqual (#lwes_event{name = "foo",
2009 attrs = [{?LWES_INT_64,cat,-9223372036854775808}]},
2010 set_int64 (new(foo),cat,-9223372036854775808)),
2011 ?_assertEqual (#lwes_event{name = "foo",
2012 attrs = [{?LWES_INT_64,cat,9223372036854775807}]},
2013 set_int64 (new(foo),cat,9223372036854775807)),
2014 ?_assertEqual (#lwes_event{name = "foo",
2015 attrs = [{?LWES_INT_64_ARRAY,cat,
2016 [1,0,-1]}]},
2017 set_int64_array (new(foo),cat,[1,0,-1])),
2018 ?_assertError (badarg,
2019 set_int64_array (new(foo),cat,a)),
2020 ?_assertEqual (#lwes_event{name = "foo",
2021 attrs = [{?LWES_N_INT_64_ARRAY,cat,
2022 [-1,0,undefined]}]},
2023 set_nint64_array (new(foo),cat,
2024 [-1,0,undefined])),
2025 ?_assertError (badarg,
2026 set_nint64_array (new(foo),cat,a)),
2027 % INT64 bounds tests
2028 ?_assertError (badarg,
2029 set_int64 (new(foo),cat,9223372036854775808)),
2030 ?_assertError (badarg,
2031 set_int64 (new(foo),cat,-9223372036854775809)),
2033 % UINT64 tests
2034 ?_assertEqual (#lwes_event{name = "foo",
2035 attrs = [{?LWES_U_INT_64,cat,0}]},
2036 set_uint64 (new(foo),cat,0)),
2037 ?_assertEqual (#lwes_event{name = "foo",
2038 attrs = [{?LWES_U_INT_64,cat,50}]},
2039 set_uint64 (new(foo),cat,50)),
2040 ?_assertEqual (#lwes_event{name = "foo",
2041 attrs = [{?LWES_U_INT_64,cat,18446744073709551615}]},
2042 set_uint64 (new(foo),cat,18446744073709551615)),
2043 ?_assertEqual (#lwes_event{name = "foo",
2044 attrs = [{?LWES_U_INT_64_ARRAY,cat,
2045 [1,0,1]}]},
2046 set_uint64_array (new(foo),cat,[1,0,1])),
2047 ?_assertError (badarg,
2048 set_uint64_array (new(foo),cat,a)),
2049 ?_assertEqual (#lwes_event{name = "foo",
2050 attrs = [{?LWES_N_U_INT_64_ARRAY,cat,
2051 [1,0,undefined]}]},
2052 set_nuint64_array (new(foo),cat,
2053 [1,0,undefined])),
2054 ?_assertError (badarg,
2055 set_nuint64_array (new(foo),cat,a)),
2056 % UINT64 bounds tests
2057 ?_assertError (badarg,
2058 set_uint64 (new(foo),cat,-5)),
2059 ?_assertError (badarg,
2060 set_uint64 (new(foo),cat,18446744073709551616)),
2061 % BOOLEAN tests
2062 ?_assertEqual (#lwes_event{name = "foo",
2063 attrs = [{?LWES_BOOLEAN,cat,true}]},
2064 set_boolean (new(foo),cat,true)),
2065 ?_assertEqual (#lwes_event{name = "foo",
2066 attrs = [{?LWES_BOOLEAN,cat,false}]},
2067 set_boolean (new(foo),cat,false)),
2068 ?_assertError (badarg,
2069 set_boolean (new(foo),cat,kinda)),
2070 ?_assertEqual (#lwes_event{name = "foo",
2071 attrs = [{?LWES_BOOLEAN_ARRAY,cat,
2072 [true,false,true]}]},
2073 set_boolean_array (new(foo),cat,[true,false,true])),
2074 ?_assertError (badarg,
2075 set_boolean_array (new(foo),cat,a)),
2076 ?_assertEqual (#lwes_event{name = "foo",
2077 attrs = [{?LWES_N_BOOLEAN_ARRAY,cat,
2078 [true,false,undefined]}]},
2079 set_nboolean_array (new(foo),cat,
2080 [true,false,undefined])),
2081 ?_assertError (badarg,
2082 set_nboolean_array (new(foo),cat,a)),
2083 % IP_ADDR test
2084 ?_assertEqual (#lwes_event{name = "foo",
2085 attrs = [{?LWES_IP_ADDR,cat,{127,0,0,1}}]},
2086 set_ip_addr (new(foo),cat,{127,0,0,1})),
2087 ?_assertEqual (#lwes_event{name = "foo",
2088 attrs = [{?LWES_IP_ADDR,cat,{127,0,0,1}}]},
2089 set_ip_addr (new(foo),cat,"127.0.0.1")),
2090 ?_assertEqual (#lwes_event{name = "foo",
2091 attrs = [{?LWES_IP_ADDR,cat,{127,0,0,1}}]},
2092 set_ip_addr (new(foo),cat,<<"127.0.0.1">>)),
2093 ?_assertError (badarg,
2094 set_ip_addr (new(foo),cat,"300.300.300.300")),
2095 ?_assertEqual (#lwes_event{name = "foo",
2096 attrs = [{?LWES_IP_ADDR_ARRAY,cat,
2097 [{127,0,0,1},{10,0,0,1},{25,26,27,28}]}]},
2098 set_ip_addr_array (new(foo),cat,
2099 ["127.0.0.1","10.0.0.1","25.26.27.28"])),
2100 ?_assertError (badarg,
2101 set_ip_addr_array (new(foo),cat,a)),
2103 % STRING tests
2104 ?_assertEqual (#lwes_event{name = "foo",
2105 attrs = [{?LWES_STRING,cat,"true"}]},
2106 set_string (new(foo),cat,"true")),
2107 ?_assertError (badarg,
2108 set_string (new(foo),cat,123)),
2109 ?_assertEqual (#lwes_event{name = "foo",
2110 attrs = [{?LWES_STRING_ARRAY,cat,
2111 ["hello","world","!"]}]},
2112 set_string_array (new(foo),cat,["hello","world","!"])),
2113 ?_assertError (badarg,
2114 set_string_array (new(foo),cat,a)),
2115 ?_assertEqual (#lwes_event{name = "foo",
2116 attrs = [{?LWES_N_STRING_ARRAY,cat,
2117 ["hello","world",undefined]}]},
2118 set_nstring_array (new(foo),cat,
2119 ["hello","world",undefined])),
2120 ?_assertError (badarg,
2121 set_nstring_array (new(foo),cat,a)),
2122 % LONG STRING tests
2123 ?_assertEqual (#lwes_event{name = "foo",
2124 attrs = [{?LWES_LONG_STRING,cat,<<"true">>}]},
2125 set_long_string (new(foo),cat,<<"true">>)),
2126 ?_assertError (badarg,
2127 set_long_string (new(foo),cat,123)),
2128 % BYTE tests
2129 ?_assertEqual (#lwes_event{name = "foo",
2130 attrs = [{?LWES_BYTE,cat,123}]},
2131 set_byte (new(foo),cat,123)),
2132 ?_assertError (badarg,
2133 set_byte (new(foo),cat,300)),
2134 ?_assertEqual (#lwes_event{name = "foo",
2135 attrs = [{?LWES_BYTE_ARRAY,cat,
2136 [5,1,6]}]},
2137 set_byte_array (new(foo),cat,[5,1,6])),
2138 ?_assertError (badarg,
2139 set_byte_array (new(foo),cat,a)),
2140 ?_assertEqual (#lwes_event{name = "foo",
2141 attrs = [{?LWES_N_BYTE_ARRAY,cat,
2142 [undefined,1,6]}]},
2143 set_nbyte_array (new(foo),cat,
2144 [undefined,1,6])),
2145 ?_assertError (badarg,
2146 set_nbyte_array (new(foo),cat,a)),
2147 % FLOAT tests
2148 ?_assertEqual (#lwes_event{name = "foo",
2149 attrs = [{?LWES_FLOAT,cat,5.85253}]},
2150 set_float (new(foo),cat,5.85253)),
2151 ?_assertError (badarg,
2152 set_float (new(foo),cat,a)),
2153 ?_assertEqual (#lwes_event{name = "foo",
2154 attrs = [{?LWES_FLOAT_ARRAY,cat,
2155 [5.85253,1.23456,6.254335]}]},
2156 set_float_array (new(foo),cat,[5.85253,1.23456,6.254335])),
2157 ?_assertError (badarg,
2158 set_float_array (new(foo),cat,a)),
2159 ?_assertEqual (#lwes_event{name = "foo",
2160 attrs = [{?LWES_N_FLOAT_ARRAY,cat,
2161 [undefined,1.23456,6.254335]}]},
2162 set_nfloat_array (new(foo),cat,
2163 [undefined,1.23456,6.254335])),
2164 ?_assertError (badarg,
2165 set_nfloat_array (new(foo),cat,a)),
2166 % DOUBLE tests
2167 ?_assertEqual (#lwes_event{name = "foo",
2168 attrs = [{?LWES_DOUBLE,cat,5.85253}]},
2169 set_double (new(foo),cat,5.85253)),
2170 ?_assertError (badarg,
2171 set_double (new(foo),cat,a)),
2172 ?_assertEqual (#lwes_event{
2173 name = "foo",
2174 attrs = [{?LWES_DOUBLE_ARRAY,cat,
2175 [5.85253,1.23456,6.254335]}]},
2176 set_double_array (new(foo),cat,
2177 [5.85253,1.23456,6.254335])),
2178 ?_assertError (badarg,
2179 set_double_array (new(foo),cat,a)),
2180 ?_assertEqual (#lwes_event{
2181 name = "foo",
2182 attrs = [{?LWES_N_DOUBLE_ARRAY,cat,
2183 [5.85253,undefined,6.254335]}]},
2184 set_ndouble_array (new(foo),cat,
2185 [5.85253,undefined,6.254335])),
2186 ?_assertError (badarg,
2187 set_ndouble_array (new(foo),cat,a))
2193 long_string_test_ () ->
2194 B = large_bin (),
2195 L = large_list (),
2197 { "long string binary",
2198 fun() ->
2199 ?assertEqual (
2200 #lwes_event {name = <<"foo">>, attrs = [{<<"bar">>, B}]},
2201 from_binary (
2202 to_binary (
2203 #lwes_event {name = <<"foo">>, attrs = [{ "bar", B}]}
2207 { "long string list",
2208 fun() ->
2209 ?assertEqual (
2210 #lwes_event {name = <<"foo">>, attrs = [{<<"bar">>, B}]},
2211 from_binary (
2212 to_binary (
2213 #lwes_event {name = <<"foo">>, attrs = [{ "bar", L}]}
2219 large_bin () ->
2220 lists:foldl (fun (_, A) ->
2221 <<$a:8, A/binary>>
2222 end,
2223 <<>>,
2224 lists:seq (1, 99999)).
2225 large_list () ->
2226 lists:foldl(fun (_, A) ->
2227 [ $a | A ]
2228 end,
2230 lists:seq (1,99999)).
2232 allow_atom_and_binary_for_strings_test_ () ->
2233 [ ?_assertEqual (
2234 #lwes_event {name = <<"foo">>,attrs=[{<<"bar">>,<<"baz">>}]},
2235 from_binary(
2236 to_binary(
2237 #lwes_event {name="foo", attrs=[{"bar",baz}]}
2241 ?_assertEqual (
2242 #lwes_event {name = <<"foo">>,attrs=[{<<"bar">>,<<"baz">>}]},
2243 from_binary(
2244 to_binary(
2245 #lwes_event {name="foo", attrs=[{"bar",<<"baz">>}]}
2249 ?_assertEqual (
2250 #lwes_event {name = <<"foo">>,attrs=[{<<"bar">>,<<"baz">>}]},
2251 from_binary(
2252 to_binary(
2253 #lwes_event {name="foo", attrs=[{"bar","baz"}]}
2259 set_nullable_array_test_ () ->
2261 ?_assertEqual (#lwes_event {name = "foo",
2262 attrs = [ { ?LWES_N_INT_16_ARRAY, key1,
2263 [1, -1, undefined, 3, undefined, -4]}]},
2264 set_nint16_array(new(foo),
2265 key1, [1, -1, undefined, 3, undefined, -4])
2269 write_read_nullarrays_test_() ->
2270 [ fun () ->
2271 W = write(Type, Arr),
2272 <<_:8/bits, Data/binary>> = W,
2273 ?assertEqual ({Arr, <<>>}, read_value(Type_Id, Data))
2275 || {Type, Type_Id, Arr}
2276 <- [
2277 {?LWES_N_U_INT_16_ARRAY, 141, [3, undefined, undefined, 500, 10]},
2278 {?LWES_N_INT_16_ARRAY, 142, [undefined, -1, undefined, -500, 10]},
2279 {?LWES_N_U_INT_32_ARRAY, 143, [3, undefined, undefined, 500, 10]},
2280 {?LWES_N_INT_32_ARRAY, 144, [undefined, -1, undefined, -500, 10]},
2281 {?LWES_N_U_INT_64_ARRAY, 148, [3, 1844674407370955161, undefined, 10]},
2282 {?LWES_N_INT_64_ARRAY, 147, [undefined, undefined, -72036854775808]},
2283 {?LWES_N_BOOLEAN_ARRAY, 149, [true, false, undefined, true, true, false]},
2284 {?LWES_N_BYTE_ARRAY, 150, [undefined, undefined, undefined, 23, 72, 9]},
2285 {?LWES_N_FLOAT_ARRAY, 151, [undefined, -2.25, undefined, 2.25]},
2286 {?LWES_N_DOUBLE_ARRAY, 152, [undefined, undefined, -1.25, 2.25]},
2287 {?LWES_N_STRING_ARRAY, 145, [undefined, <<"test">>, <<"should ">>, <<"pass">>]}
2291 string_nullable_arrays_test_ () ->
2293 ?_assertEqual(write(?LWES_N_STRING_ARRAY, [undefined, "test", "should ", "pass"]),
2294 <<145,0,4,0,4,14,0,4,"test",0,7,"should ",0,4,"pass">>),
2296 ?_assertEqual({[undefined, <<"test">>, <<"should ">>, <<"pass">>], <<>>},
2297 read_value(?LWES_TYPE_N_STRING_ARRAY,
2298 <<0,4,0,4,14,0,4,"test",0,7,"should ",0,4,"pass">>))
2301 serialize_test_ () ->
2303 ?_assertEqual (test_packet(binary),
2304 to_binary(
2305 remove_attr(<<"ReceiptTime">>,
2306 remove_attr(<<"SenderIP">>,
2307 remove_attr(<<"SenderPort">>,
2308 test_packet(tagged)))))
2310 fun () ->
2311 E = #lwes_event { name = <<"test">>,
2312 attrs = dict:from_list([{<<"a">>,<<"b">>},{<<"c">>,1}])
2314 ?assertEqual (E, from_binary (to_binary(E),dict))
2318 deserialize_test_ () ->
2319 { setup,
2320 fun () ->
2321 {ok, Port} = gen_udp:open(0,[binary]),
2322 {udp, Port, {192,168,54,1}, 58206, test_packet(binary)}
2323 end,
2324 fun ({udp, Port, _, _, _}) ->
2325 gen_udp:close(Port)
2326 end,
2327 fun (Packet) ->
2329 { "peek name check",
2330 ?_assertEqual (<<"Test">>, peek_name_from_udp (Packet))
2332 { "peek name failure",
2333 fun () ->
2334 {ok, Port} = gen_udp:open(0,[binary]),
2335 ?assertEqual ({error, malformed_event},
2336 peek_name_from_udp ({udp, Port,
2337 {192,168,54,1}, 58206,
2338 <<4,84,101,115>>})),
2339 gen_udp:close(Port)
2342 { "serialize dict",
2343 fun() ->
2344 % need to normalize dict's otherwise they fail to compare equal
2345 EIn = #lwes_event { attrs = DictIn } =
2346 remove_attr (<<"ReceiptTime">>, test_packet (dict)),
2347 EInSorted =
2348 EIn#lwes_event {
2349 attrs = dict:from_list(lists:sort(dict:to_list(DictIn))) },
2350 EOut = #lwes_event { attrs = DictOut } =
2351 remove_attr (<<"ReceiptTime">>, from_udp_packet(Packet, dict)),
2352 EOutSorted =
2353 EOut#lwes_event {
2354 attrs = dict:from_list(lists:sort(dict:to_list(DictOut))) },
2355 ?assertEqual (EOutSorted, EInSorted)
2359 { lists:flatten(io_lib:format("serialize ~p",[Format])),
2360 ?_assertEqual (
2361 remove_attr (<<"ReceiptTime">>, from_udp_packet(Packet, Format)),
2362 remove_attr (<<"ReceiptTime">>, test_packet (Format))
2364 } || Format <- formats(), Format =/= dict
2370 nested_json_test_ () ->
2372 { "event -> binary", ?_assertEqual (to_binary(nested_event(event)), nested_event(binary)) },
2373 % check that all untyped types encode to the same json structure
2374 { "json -> untyped",
2375 ?_assertEqual (lwes_mochijson2:encode(nested_event(json)),
2376 lwes_mochijson2:encode(nested_event(json_untyped))) },
2377 { "json -> proplist",
2378 ?_assertEqual (lwes_mochijson2:encode(nested_event(json)),
2379 lwes_mochijson2:encode(nested_event(json_proplist))) },
2380 { "json -> proplist_untyped",
2381 ?_assertEqual (lwes_mochijson2:encode(nested_event(json)),
2382 lwes_mochijson2:encode(nested_event(json_proplist_untyped)))},
2383 { "json -> eep18",
2384 ?_assertEqual (lwes_mochijson2:encode(nested_event(json)),
2385 lwes_mochijson2:encode(nested_event(json_eep18))) },
2386 { "json -> eep18_untyped",
2387 ?_assertEqual (lwes_mochijson2:encode(nested_event(json)),
2388 lwes_mochijson2:encode(nested_event(json_eep18_untyped))) },
2389 % check that all typed typed encode to the same json structure
2390 { "json_typed -> proplist_typed",
2391 ?_assertEqual (lwes_mochijson2:encode(nested_event(json_typed)),
2392 lwes_mochijson2:encode(nested_event(json_proplist_typed)))},
2393 { "json_typed -> eep18_typed",
2394 ?_assertEqual (lwes_mochijson2:encode(nested_event(json_typed)),
2395 lwes_mochijson2:encode(nested_event(json_eep18_typed)))}
2397 { lists:flatten(io_lib:format("~p -> ~p",[Format,Format])),
2398 ?_assertEqual (to_json(nested_event(binary), Format),
2399 nested_event (Format)) }
2400 || Format
2401 <- json_formats()
2405 % had a bug with arrays in json sometimes being misinterpreted, the first
2406 % test was a failing test and other may be added if additional issues
2407 % are found
2408 arrays_in_json_test_ () ->
2410 ?_assertEqual(
2411 {[{<<"EventName">>,<<"Foo::Bar">>},
2412 {<<"typed">>,
2413 {[{<<"cat">>,
2414 {[{<<"type">>,?LWES_N_STRING_ARRAY},
2415 {<<"value">>,[<<"4458534">>,<<>>,<<"29681110">>]}]}}]}}]
2417 lwes_event:to_json(
2418 #lwes_event { name = <<"Foo::Bar">>,
2419 attrs = [{?LWES_N_STRING_ARRAY,<<"cat">>,
2420 [<<"4458534">>,<<"">>,<<"29681110">>]}]})
2425 from_json_test () ->
2426 #lwes_event{name=_,attrs=AttributesFromJson} = from_json(test_text()),
2427 #lwes_event{name=_,attrs=AttributesFromTest} = test_packet(tagged),
2428 ?assertEqual(lists:sort(AttributesFromJson),
2429 lists:sort(
2430 remove_attr(<<"ReceiptTime">>,AttributesFromTest))).
2432 check_headers_test_ () ->
2433 PacketWithHeaders =
2434 <<19,77,111,110,68,101,109,97,110,100,58,58,83,116,97,116,115,
2435 77,115,103,0,14,7,99,116,120,116,95,118,48,5,0,15,111,112,101,
2436 110,120,45,100,101,118,46,108,111,99,97,108,7,99,116,120,116,
2437 95,107,48,5,0,4,104,111,115,116,8,99,116,120,116,95,110,117,
2438 109,1,0,1,2,116,49,5,0,5,103,97,117,103,101,2,118,49,7,0,0,0,
2439 0,0,0,2,208,2,107,49,5,0,9,114,116,113,95,98,121,116,101,115,
2440 2,116,48,5,0,5,103,97,117,103,101,2,118,48,7,0,0,0,0,6,64,0,0,
2441 2,107,48,5,0,13,114,116,113,95,109,97,120,95,98,121,116,101,
2442 115,3,110,117,109,1,0,2,7,112,114,111,103,95,105,100,5,0,4,
2443 114,105,97,107,11,82,101,99,101,105,112,116,84,105,109,101,7,
2444 0,0,1,79,66,126,41,176,8,83,101,110,100,101,114,73,80,6,128,
2445 101,16,172,10,83,101,110,100,101,114,80,111,114,116,1,135,217>>,
2446 PacketWithoutHeaders =
2447 <<19,77,111,110,68,101,109,97,110,100,58,58,83,116,97,116,115,
2448 77,115,103,0,14,7,99,116,120,116,95,118,48,5,0,15,111,112,101,
2449 110,120,45,100,101,118,46,108,111,99,97,108,7,99,116,120,116,
2450 95,107,48,5,0,4,104,111,115,116,8,99,116,120,116,95,110,117,
2451 109,1,0,1,2,116,49,5,0,5,103,97,117,103,101,2,118,49,7,0,0,0,
2452 0,0,0,2,208,2,107,49,5,0,9,114,116,113,95,98,121,116,101,115,
2453 2,116,48,5,0,5,103,97,117,103,101,2,118,48,7,0,0,0,0,6,64,0,0,
2454 2,107,48,5,0,13,114,116,113,95,109,97,120,95,98,121,116,101,
2455 115,3,110,117,109,1,0,2,7,112,114,111,103,95,105,100,5,0,4,
2456 114,105,97,107>>,
2458 ?_assertEqual (true, has_header_fields (PacketWithHeaders)),
2459 ?_assertEqual (false, has_header_fields (PacketWithoutHeaders)),
2460 fun () ->
2461 E1 = #lwes_event{name = <<"test">>,
2462 attrs = [
2463 {uint16,<<"SenderPort">>,58206},
2464 {ip_addr,<<"SenderIP">>,{192,168,54,1}},
2465 {int64,<<"ReceiptTime">>,1439587738948},
2466 {string,<<"foo">>,<<"bar">>}
2468 B1 = to_binary(E1),
2469 ?assertEqual (true, has_header_fields (B1)),
2470 {ok, Port} = gen_udp:open (0, [binary]), % so the packets below work
2471 E2 = from_udp_packet({udp,Port,{127,0,0,1},24442,B1},tagged),
2472 gen_udp:close(Port),
2473 ?assertEqual (E1, E2)
2474 end,
2475 fun () ->
2476 H = header_fields_to_iolist(12345253,{127,0,0,1},20202),
2477 ?assertEqual(true,
2478 has_header_fields(erlang:iolist_to_binary(H))),
2479 EventNoHeaders =
2480 #lwes_event { name = <<"foo">>,
2481 attrs = [{string, <<"bar">>,<<"baz">>}]},
2482 ExpectedEvent =
2483 #lwes_event { name = <<"foo">>,
2484 attrs = [{uint16,<<"SenderPort">>,20202},
2485 {ip_addr,<<"SenderIP">>,{127,0,0,1}},
2486 {int64,<<"ReceiptTime">>,12345253},
2487 {string,<<"bar">>,<<"baz">>}] },
2488 ?assertEqual (ExpectedEvent,
2489 from_binary (
2490 erlang:iolist_to_binary (
2491 [ to_binary (EventNoHeaders), H ]
2493 tagged
2498 % tests for odd case mostly just for coverage numbers
2499 coverage_test_ () ->
2501 { "to_binary/1 passthrough",
2502 ?_assertEqual (test_packet(binary), to_binary(test_packet(binary))) },
2503 { "from_binary/1 empty binary",
2504 ?_assertEqual (undefined, from_binary(<<>>)) },
2505 { "from_udp_packet/2 with receipt time",
2506 fun () ->
2507 B = lwes_event:to_binary(lwes_event:new(foo)),
2508 % if the second element of the udp tuple is a number and not
2509 % a port, that number will be used for ReceiptTime
2510 P = {udp, 5, {127,0,0,1}, 50, B},
2511 E = #lwes_event{name = <<"foo">>,
2512 attrs = [{<<"SenderIP">>,{127,0,0,1}},
2513 {<<"SenderPort">>,50},
2514 {<<"ReceiptTime">>,5}]},
2515 ?assertEqual (E, lwes_event:from_udp_packet (P, list))
2516 end }
2519 type_inference_test_ () ->
2521 % basic non-array type inference
2522 { "integer : lower bound exceeded",
2523 ?_assertError (badarg, infer_type(-92233720368547758080)) },
2524 { "int64 : lower range",
2525 ?_assertEqual (?LWES_INT_64, infer_type(-21474836480)) },
2526 { "int32 : lower range",
2527 ?_assertEqual (?LWES_INT_32, infer_type(-2147483648)) },
2528 { "int16 : lower range",
2529 ?_assertEqual (?LWES_INT_16, infer_type(-32768)) },
2530 { "byte : lower range",
2531 ?_assertEqual (?LWES_BYTE, infer_type(0)) },
2532 { "byte : upper range",
2533 ?_assertEqual (?LWES_BYTE, infer_type(255)) },
2534 { "int16 : upper range",
2535 ?_assertEqual (?LWES_INT_16, infer_type(32767)) },
2536 { "uint16 : upper range",
2537 ?_assertEqual (?LWES_U_INT_16, infer_type(65535)) },
2538 { "int32 : upper range",
2539 ?_assertEqual (?LWES_INT_32, infer_type(2147483647)) },
2540 { "uint32 : upper range",
2541 ?_assertEqual (?LWES_U_INT_32, infer_type(4294967295)) },
2542 { "int64 : upper range",
2543 ?_assertEqual (?LWES_INT_64, infer_type(9223372036854775807)) },
2544 { "uint64 : upper range",
2545 ?_assertEqual (?LWES_U_INT_64, infer_type(18446744073709551615)) },
2546 { "integer : upper range exceeded",
2547 ?_assertError (badarg, infer_type(18446744073709551616)) },
2548 { "boolean : true",
2549 ?_assertEqual (?LWES_BOOLEAN, infer_type(true)) },
2550 { "boolean : false",
2551 ?_assertEqual (?LWES_BOOLEAN, infer_type(false)) },
2552 { "ip_addr : good address",
2553 ?_assertEqual (?LWES_IP_ADDR, infer_type({127,0,0,1})) },
2554 { "ip_addr : bad address",
2555 ?_assertError (badarg, infer_type({300,0,0,1})) },
2556 { "float/double",
2557 ?_assertEqual (?LWES_DOUBLE, infer_type(3.14)) },
2558 { "string : list of small integers",
2559 ?_assertEqual (?LWES_STRING, infer_type([$c,$a,$t])) },
2560 { "string : atoms count as strings",
2561 ?_assertEqual (?LWES_STRING, infer_type('cat')) },
2562 { "string : binaries count as strings",
2563 ?_assertEqual (?LWES_STRING, infer_type(<<"cat">>)) },
2564 { "string : iolists count as strings",
2565 ?_assertEqual (?LWES_STRING, infer_type([$c,"a",<<"t">>])) },
2566 { "string : iolists which are improper lists count as strings",
2567 ?_assertEqual (?LWES_STRING, infer_type([$c,"a"|<<"t">>])) },
2569 % array type inference
2571 { "uint16 array",
2572 ?_assertEqual(?LWES_U_INT_16_ARRAY, infer_type([0,65535,32,85])) },
2573 { "int16 array",
2574 ?_assertEqual(?LWES_INT_16_ARRAY, infer_type([-32768,32767,-32,85])) },
2575 { "uint32 array",
2576 ?_assertEqual(?LWES_U_INT_32_ARRAY, infer_type([0,65535,32,85,4294967295])) },
2577 { "int32 array",
2578 ?_assertEqual(?LWES_INT_32_ARRAY, infer_type([-32769,-32768,32767,-32,85, 65535])) },
2579 { "uint64 array",
2580 ?_assertEqual(?LWES_U_INT_64_ARRAY, infer_type([0,65535,32,85,4294967295, 18446744073709551615])) },
2581 { "int64 array",
2582 ?_assertEqual(?LWES_INT_64_ARRAY, infer_type([-9223372036854775807, -32769,-32768,32767,-32,85, 65535])) },
2583 { "string array : with atoms these are detectable",
2584 ?_assertEqual(?LWES_STRING_ARRAY, infer_type([foo,bar])) },
2585 { "string array : with atoms these are detectable",
2586 ?_assertEqual(?LWES_STRING_ARRAY, infer_type([foo,"bar"])) },
2587 { "string array : with atoms these are detectable",
2588 ?_assertEqual(?LWES_STRING_ARRAY, infer_type([foo,["bar"|<<"baz">>]])) },
2589 { "boolean array",
2590 ?_assertEqual(?LWES_BOOLEAN_ARRAY, infer_type([true,false,true])) },
2591 { "ip_addr array",
2592 ?_assertEqual(?LWES_IP_ADDR_ARRAY, infer_type([{127,0,0,1},{255,255,255,255}])) },
2593 { "float/double array",
2594 ?_assertEqual(?LWES_DOUBLE_ARRAY, infer_type([3.14159,2.0]))
2597 % nullable array type inference
2598 { "nullable uint16 array",
2599 ?_assertEqual(?LWES_N_U_INT_16_ARRAY, infer_type([undefined, 0,65535,32,85])) },
2600 { "nullable int16 array",
2601 ?_assertEqual(?LWES_N_INT_16_ARRAY, infer_type([-32768,undefined,32767,-32,85])) },
2602 { "nullable uint32 array",
2603 ?_assertEqual(?LWES_N_U_INT_32_ARRAY, infer_type([0,65535,32,85,undefined,4294967295])) },
2604 { "nullable int32 array",
2605 ?_assertEqual(?LWES_N_INT_32_ARRAY, infer_type([-32769,-32768,32767,-32,85, 65535,undefined])) },
2606 { "nullable uint64 array",
2607 ?_assertEqual(?LWES_N_U_INT_64_ARRAY, infer_type([0,undefined,65535,undefined,4294967295, 18446744073709551615])) },
2608 { "nullable int64 array",
2609 ?_assertEqual(?LWES_N_INT_64_ARRAY, infer_type([-9223372036854775807, -32769,undefined,32767,-32,85, 65535])) },
2610 { "nullable string array 1",
2611 ?_assertEqual(?LWES_N_STRING_ARRAY, infer_type(["foo",undefined,"bar"])) },
2612 { "nullable string array 2",
2613 ?_assertEqual(?LWES_N_STRING_ARRAY, infer_type([foo,"bar",undefined])) },
2614 { "nullable string array 3",
2615 ?_assertEqual(?LWES_N_STRING_ARRAY, infer_type([undefined,foo,["bar"|<<"baz">>]])) },
2616 { "nullable byte array : only detectable form",
2617 ?_assertEqual(?LWES_N_BYTE_ARRAY, infer_type([undefined,$c,$a,$t])) },
2618 { "nullable boolean array",
2619 ?_assertEqual(?LWES_N_BOOLEAN_ARRAY, infer_type([true,false,true, undefined])) },
2620 { "nullable ip_addr array is not implemented",
2621 ?_assertError(badarg, infer_type([{127,0,0,1},undefined,{255,255,255,255}])) },
2622 { "nullable float/double",
2623 ?_assertEqual(?LWES_N_DOUBLE_ARRAY, infer_type([3.14159,undefined,2.0]))
2628 % coverage cases
2633 -endif.