./ct_report/coverage/mod_muc_light_room_config.COVER.html

1 %%%----------------------------------------------------------------------
2 %%% File : mod_muc_light_room_config.erl
3 %%% Author : Piotr Nosek <piotr.nosek@erlang-solutions.com>
4 %%% Purpose : Stateless utilities for room config processing
5 %%% Created : 15 Nov 2019 by Piotr Nosek <piotr.nosek@erlang-solutions.com>
6 %%%
7 %%% This program is free software; you can redistribute it and/or
8 %%% modify it under the terms of the GNU General Public License as
9 %%% published by the Free Software Foundation; either version 2 of the
10 %%% License, or (at your option) any later version.
11 %%%
12 %%% This program is distributed in the hope that it will be useful,
13 %%% but WITHOUT ANY WARRANTY; without even the implied warranty of
14 %%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 %%% General Public License for more details.
16 %%%
17 %%% You should have received a copy of the GNU General Public License
18 %%% along with this program; if not, write to the Free Software
19 %%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 %%%
21 %%%----------------------------------------------------------------------
22
23 -module(mod_muc_light_room_config).
24
25 %% API
26 -export([from_binary_kv_diff/2, from_binary_kv/2,
27 to_binary_kv_diff/2, to_binary_kv/2]).
28
29 -include("mod_muc_light.hrl").
30
31 -export_type([binary_kv/0, kv/0, schema/0]).
32
33 %% Config primitives
34 -type key() :: atom().
35 -type value() :: binary() | integer() | float().
36 -type value_type() :: binary | integer | float.
37
38 %% Actual config
39 -type item() :: {key(), value()}.
40 -type kv() :: [item()].
41 -type binary_kv() :: [{Key :: binary(), Value :: binary()}].
42
43 %% User definition processing
44 -type schema_item() :: {FieldName :: binary(), DefaultValue :: value(), key(), value_type()}.
45 -type schema() :: [schema_item()]. % has to be sorted
46
47 %%====================================================================
48 %% API
49 %%====================================================================
50
51 %% Guarantees that config will have unique fields
52 -spec from_binary_kv_diff(RawConfig :: binary_kv(), ConfigSchema :: schema()) ->
53 {ok, kv()} | validation_error().
54 from_binary_kv_diff(RawConfig, ConfigSchema) ->
55 31 take_next(lists:ukeysort(1, RawConfig), ConfigSchema, true, fun take_next_kv/2, []).
56
57 -spec from_binary_kv(RawConfig :: binary_kv(), ConfigSchema :: schema()) ->
58 {ok, kv()} | validation_error().
59 from_binary_kv(RawConfig, ConfigSchema) ->
60 520 take_next(lists:ukeysort(1, RawConfig), ConfigSchema, false, fun take_next_kv/2, []).
61
62 -spec to_binary_kv_diff(RawConfig :: kv(), ConfigSchema :: schema()) ->
63 {ok, binary_kv()} | validation_error().
64 to_binary_kv_diff(RawConfig, ConfigSchema) ->
65 29 take_next(lists:ukeysort(1, RawConfig), ConfigSchema, true, fun take_next_binary_kv/2, []).
66
67 -spec to_binary_kv(Config :: kv(), ConfigSchema :: schema()) ->
68 {ok, binary_kv()} | validation_error().
69 to_binary_kv(RawConfig, ConfigSchema) ->
70 443 take_next(lists:ukeysort(1, RawConfig), ConfigSchema, false, fun take_next_binary_kv/2, []).
71
72 take_next([], [], _, _, Config) ->
73 1020 {ok, Config};
74 take_next(RawConfig, ConfigSchema, DropDefaults, TakeNext, Config) ->
75 2532 case {DropDefaults, TakeNext(RawConfig, ConfigSchema)} of
76 {true, {default, RRawConfig, RConfigSchema, _}} ->
77 % do not populate the diff with default values
78 56 take_next(RRawConfig, RConfigSchema, DropDefaults, TakeNext, Config);
79 {_, {_, RRawConfig, RConfigSchema, KV}} ->
80 2473 take_next(RRawConfig, RConfigSchema, DropDefaults, TakeNext, [KV | Config]);
81 {_, {error, Reason}} ->
82 3 {error, Reason}
83 end.
84
85 %%====================================================================
86 %% Internal functions
87 %%====================================================================
88
89 take_next_kv([{KeyBin, ValBin} | RRawConfig], [{KeyBin, _Default, Key, Type} | RSchema]) ->
90 605 try {value, RRawConfig, RSchema, {Key, b2value(ValBin, Type)}}
91 1 catch _:_ -> {error, {KeyBin, type_error}}
92 end;
93 take_next_kv(RawConfig, [{_KeyBin, Default, Key, _Type} | RSchema]) ->
94 767 {default, RawConfig, RSchema, {Key, Default}};
95 take_next_kv([{KeyBin, _} | _], _) ->
96 2 {error, {KeyBin, not_found}}.
97
98 take_next_binary_kv([{Key, ValBin} | RRawConfig], [{KeyBin, _Default, Key, Type} | RSchema]) ->
99 1131 try {value, RRawConfig, RSchema, {KeyBin, value2b(ValBin, Type)}}
100
:-(
catch _:_ -> {error, {KeyBin, type_error}}
101 end;
102 take_next_binary_kv(RawConfig, [{KeyBin, Default, _Key, _Type} | RSchema]) ->
103 27 {default, RawConfig, RSchema, {KeyBin, Default}};
104 take_next_binary_kv([{KeyBin, _} | _], _) ->
105
:-(
{error, {KeyBin, not_found}}.
106
107 -spec b2value(ValBin :: binary(), Type :: value_type()) -> Converted :: value().
108 604 b2value(ValBin, binary) when is_binary(ValBin) -> ValBin;
109
:-(
b2value(ValBin, integer) -> binary_to_integer(ValBin);
110
:-(
b2value(ValBin, float) -> binary_to_float(ValBin).
111
112 -spec value2b(Val :: value(), Type :: value_type()) -> Converted :: binary().
113 1131 value2b(Val, binary) when is_binary(Val) -> Val;
114
:-(
value2b(Val, integer) -> integer_to_binary(Val);
115
:-(
value2b(Val, float) -> float_to_binary(Val).
Line Hits Source