/home/runner/work/mcd/mcd/_site/ct/ct_run.ct_mcd@fv-az773-648.2023-11-24_16.44.07/mcd_protocol_meta.COVER.html

1 %% Copyright (c) 2022 Peter Morgan <peter.james.morgan@gmail.com>
2 %%
3 %% Licensed under the Apache License, Version 2.0 (the "License");
4 %% you may not use this file except in compliance with the License.
5 %% You may obtain a copy of the License at
6 %%
7 %% http://www.apache.org/licenses/LICENSE-2.0
8 %%
9 %% Unless required by applicable law or agreed to in writing, software
10 %% distributed under the License is distributed on an "AS IS" BASIS,
11 %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 %% See the License for the specific language governing permissions and
13 %% limitations under the License.
14
15
16 -module(mcd_protocol_meta).
17
18
19 -export([decode/2]).
20 -export([encode/1]).
21 -include("mcd.hrl").
22
23
24 decode(debug_reply = Command, Remainder) ->
25
:-(
[CommandLine, Encoded] = string:split(Remainder, ?RN),
26
:-(
{mcd_re:run(
27 #{meta => Command,
28 subject => CommandLine,
29 re => "(?<key>[^\\s]+) (?<internal>(\\w+=\\w+ ?)+)",
30 mapping => #{internal => fun decode_meta_debug_internal/1}}),
31 Encoded};
32
33 decode(Command, Remainder) when Command == head;
34 Command == not_stored;
35 Command == exists;
36 Command == not_found ->
37 27 [Flags, Encoded] = string:split(Remainder, ?RN),
38 27 {#{meta => Command, flags => mcd_meta_flags:decode(Flags)}, Encoded};
39
40 decode(Command, Remainder) when Command == debug;
41 Command == get;
42 Command == arithmetic;
43 Command == delete ->
44 29 [CommandLine, Encoded] = split(Remainder),
45 29 {re_run(
46 #{meta => Command,
47 subject => CommandLine,
48 re => [key, flags],
49 mapping => #{flags => fun mcd_meta_flags:decode/1}}),
50 Encoded};
51
52 decode(set = Command, Remainder) ->
53 19 [CommandLine, DataLine] = split(Remainder),
54 19 data_line(
55 re_run(
56 #{meta => Command,
57 subject => CommandLine,
58 re => [key, datalen, flags],
59 mapping => #{datalen => fun erlang:binary_to_integer/1,
60 flags => fun mcd_meta_flags:decode/1}}),
61 DataLine);
62
63 decode(Command, Remainder) when Command == no_op; Command == no_op_reply ->
64 4 [<<>>, Encoded] = split(Remainder),
65 4 {#{meta => Command}, Encoded};
66
67 decode(value = Command, Remainder) ->
68 18 [CommandLine, DataLine] = split(Remainder),
69 18 data_line(
70 re_run(
71 #{meta => Command,
72 subject => CommandLine,
73 re => [datalen, flags],
74 mapping => #{datalen => fun erlang:binary_to_integer/1,
75 flags => fun mcd_meta_flags:decode/1}}),
76 DataLine).
77
78
79 decode_meta_debug_internal(Encoded) ->
80
:-(
{match, Matches} = re:run(Encoded,
81 "(?<k>\\w+)=(?<v>\\w+)\s?",
82 [global,
83 {capture, all_names, binary}]),
84
:-(
[list_to_tuple(Match) || Match <- Matches].
85
86
87 encode(#{meta := set = Meta,
88 flags := Flags,
89 key := Key,
90 data := Data}) ->
91 19 [command(Meta),
92 " ",
93 Key,
94 " ",
95 integer_to_binary(iolist_size(Data)),
96 encode_flags(Flags),
97 ?RN,
98 Data,
99 ?RN];
100
101 encode(#{meta := value, data := Data} = Arg) when is_integer(Data) ->
102 10 ?FUNCTION_NAME(Arg#{data := integer_to_binary(Data)});
103
104 encode(#{meta := value = Meta,
105 flags := Flags,
106 data := Data}) ->
107 18 [command(Meta),
108 " ",
109 integer_to_binary(iolist_size(Data)),
110 encode_flags(Flags),
111 ?RN,
112 Data,
113 ?RN];
114
115 encode(#{meta := Meta, flags := Flags, key := Key})
116 when Meta == debug;
117 Meta == get;
118 Meta == arithmetic;
119 Meta == delete ->
120 29 [command(Meta),
121 " ",
122 Key,
123 encode_flags(Flags),
124 ?RN];
125
126 encode(#{meta := Meta, key := Key})
127 when Meta == debug; Meta == get; Meta == debug ->
128
:-(
[command(Meta), " ", Key, ?RN];
129
130 encode(#{meta := debug_reply = Meta, key := Key, internal := KV}) ->
131
:-(
[command(Meta), " ", Key, [[" ", K, "=", V] || {K, V} <- KV], ?RN];
132
133 encode(#{meta := Meta, flags := Flags}) ->
134 9 [command(Meta), encode_flags(Flags), ?RN];
135
136 encode(#{meta := Meta}) ->
137 22 [command(Meta), ?RN].
138
139
140 encode_flags([]) ->
141 15 [];
142 encode_flags(Flags) ->
143 60 [" ", mcd_meta_flags:encode(Flags)].
144
145
146 command(no_op) ->
147 2 "mn";
148 command(no_op_reply) ->
149 2 "MN";
150 command(miss) ->
151
:-(
"EN";
152 command(value) ->
153 18 "VA";
154 command(not_stored) ->
155 2 "NS";
156 command(not_found) ->
157 2 "NF";
158 command(head) ->
159 20 "HD";
160 command(exists) ->
161 3 "EX";
162 command(debug_reply) ->
163
:-(
"ME";
164 command(debug) ->
165
:-(
"me";
166 command(get) ->
167 11 "mg";
168 command(arithmetic) ->
169 16 "ma";
170 command(set) ->
171 19 "ms";
172 command(delete) ->
173 2 "md".
174
175
176 re_run(#{re := L} = Arg) when is_list(L) ->
177 66 mcd_re:run(
178 Arg#{re := lists:join(
179 "\\s*",
180 lists:map(
181 fun re/1,
182 L))}).
183
184 re(key = Arg) ->
185 48 ?FUNCTION_NAME(Arg, "[^\\s]+");
186
187 re(flags = Arg) ->
188 66 ?FUNCTION_NAME(Arg, "(\\w\\w*(\\s+\\w\\w*)*)?");
189
190 re(datalen = Arg) ->
191 37 ?FUNCTION_NAME(Arg, "\\d+").
192
193 re(Name, Expression) ->
194 151 io_lib:format("(?<~p>~s)", [Name, Expression]).
195
196
197 split(S) ->
198 70 string:split(S, ?RN).
199
200
201 data_line(#{datalen := Length} = Decoded, DataLine) ->
202 37 case DataLine of
203 <<Data:Length/bytes, ?RN, Encoded/bytes>> ->
204 37 {maps:without([datalen], Decoded#{data => Data}), Encoded};
205 _ ->
206
:-(
partial
207 end.
Line Hits Source