You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

104 line
3.2 KiB

  1. %% Copyright (c) 2012, Magnus Klaar <klaar@ninenines.eu>
  2. %%
  3. %% Permission to use, copy, modify, and/or distribute this software for any
  4. %% purpose with or without fee is hereby granted, provided that the above
  5. %% copyright notice and this permission notice appear in all copies.
  6. %%
  7. %% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. %% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. %% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10. %% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. %% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12. %% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13. %% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14. %% @doc Accessor function for goldrush event terms.
  15. -module(gre).
  16. -export([
  17. make/2,
  18. has/2,
  19. fetch/2,
  20. append/2,
  21. merge/2,
  22. find/2,
  23. keys/1,
  24. pairs/1
  25. ]).
  26. -type event() :: {list, [{atom(), term()}]}.
  27. -export_type([event/0]).
  28. %% @doc Construct an event term.
  29. -spec make(term(), [list]) -> event().
  30. make(Term, [Type]) ->
  31. {Type, Term}.
  32. %% @doc Check if a field exists in an event.
  33. -spec has(atom(), event()) -> boolean().
  34. has(Key, {list, List}) ->
  35. lists:keymember(Key, 1, List).
  36. -spec append(term(), event()) -> event().
  37. append(KeyVal, {list, List}) ->
  38. {list, [KeyVal|List]}.
  39. -spec merge(event(), event()) -> event().
  40. merge({list, AList}, {list, BList}) ->
  41. {list, lists:merge(AList, BList)}.
  42. %% @doc Get the value of a field in an event.
  43. %% The field is expected to exist in the event.
  44. -spec fetch(atom(), event()) -> term().
  45. fetch(Key, {list, List}=Event) ->
  46. case lists:keyfind(Key, 1, List) of
  47. {_, Value} -> Value;
  48. false -> erlang:error(badarg, [Key, Event])
  49. end.
  50. %% @doc Find the value of a field in an event.
  51. %% This is equivalent to testing if a field exists using {@link has/2}
  52. %% before accessing the value of the field using {@link fetch/2}.
  53. -spec find(atom(), event()) -> {true, term()} | false.
  54. find(Key, {list, List}) ->
  55. case lists:keyfind(Key, 1, List) of
  56. {_, Value} -> {true, Value};
  57. false -> false
  58. end.
  59. %% @doc Get the names of all fields in an event.
  60. -spec keys(event()) -> [atom()].
  61. keys({list, List}) ->
  62. kv_keys_(List).
  63. %% @private Get the names of all fields in a key-value list.
  64. -spec kv_keys_([{atom(), term()}]) -> [atom()].
  65. kv_keys_([{Key, _}|T]) ->
  66. [Key|kv_keys_(T)];
  67. kv_keys_([]) ->
  68. [].
  69. %% @doc Get the name and value of all fields in an event.
  70. -spec pairs(event()) -> [{atom(), term()}].
  71. pairs({list, List}) ->
  72. lists:sort(List).
  73. -ifdef(TEST).
  74. -include_lib("eunit/include/eunit.hrl").
  75. gre_test_() ->
  76. [?_assert(gre:has(a, gre:make([{a,1}], [list]))),
  77. ?_assertNot(gre:has(b, gre:make([{a,1}], [list]))),
  78. ?_assertEqual(1, gre:fetch(a, gre:make([{a,1}], [list]))),
  79. ?_assertError(badarg, gre:fetch(a, gre:make([], [list]))),
  80. ?_assertEqual([], gre:keys(gre:make([], [list]))),
  81. ?_assertEqual([a], gre:keys(gre:make([{a,1}], [list]))),
  82. ?_assertEqual([a,b], gre:keys(gre:make([{a,1},{b,2}], [list]))),
  83. ?_assertEqual([{a,1},{b,2}], gre:pairs(gre:make([{b,2},{a,1}], [list])))
  84. ].
  85. -endif.