network-infra-utility 0.3.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +21 -0
  3. data/GUIDE.md +212 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +70 -0
  6. data/Rakefile +1 -1
  7. data/bin/dns-query +836 -0
  8. data/bin/geo-doc +135 -0
  9. data/bin/geo-get +1 -1
  10. data/bin/geo-update +429 -0
  11. data/document/ASNum/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +242 -0
  12. data/document/DNSQuery/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +248 -0
  13. data/document/Geo/345/221/275/344/273/244/345/267/245/345/205/267/344/275/277/347/224/250/346/226/271/346/263/225.md +441 -0
  14. data/document/IP/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +297 -0
  15. data/document/MAC/346/250/241/345/235/227/345/212/237/350/203/275/350/257/264/346/230/216.md +296 -0
  16. data/document/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/344/275/277/347/224/250/346/226/271/346/263/225.md +764 -0
  17. data/network-infra-utility.gemspec +4 -2
  18. data/network.rb +3 -1
  19. data/service/geodb/geodb.rb +278 -1
  20. data/service/ssh/README.md +955 -0
  21. data/service/ssh/bin/ssh-client +198 -0
  22. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/345/212/237/350/203/275/351/234/200/346/261/202/346/226/207/346/241/243.md +292 -0
  23. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/257/246/347/273/206/350/256/276/350/256/241/346/226/207/346/241/243.md +1521 -0
  24. data/service/ssh/design/SSH/350/277/236/346/216/245/345/256/242/346/210/267/347/253/257/350/275/257/344/273/266/350/256/276/350/256/241/346/226/207/346/241/243.md +2493 -0
  25. data/service/ssh/ext/ssh_core/bin/ssh_core.cmd +28 -0
  26. data/service/ssh/ext/ssh_core/config/sys.config +0 -0
  27. data/service/ssh/ext/ssh_core/config/vm.args +0 -0
  28. data/service/ssh/ext/ssh_core/local_deps/jsx/CHECKSUM +1 -0
  29. data/service/ssh/ext/ssh_core/local_deps/jsx/LICENSE +21 -0
  30. data/service/ssh/ext/ssh_core/local_deps/jsx/README.md +696 -0
  31. data/service/ssh/ext/ssh_core/local_deps/jsx/VERSION +1 -0
  32. data/service/ssh/ext/ssh_core/local_deps/jsx/contents.tar.gz +0 -0
  33. data/service/ssh/ext/ssh_core/local_deps/jsx/metadata.config +15 -0
  34. data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.config +17 -0
  35. data/service/ssh/ext/ssh_core/local_deps/jsx/rebar.lock +1 -0
  36. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.app.src +10 -0
  37. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx.erl +506 -0
  38. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.erl +393 -0
  39. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_config.hrl +18 -0
  40. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_consult.erl +81 -0
  41. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_decoder.erl +1909 -0
  42. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_encoder.erl +116 -0
  43. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_parser.erl +1214 -0
  44. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_json.erl +408 -0
  45. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_to_term.erl +389 -0
  46. data/service/ssh/ext/ssh_core/local_deps/jsx/src/jsx_verify.erl +121 -0
  47. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx.erl +506 -0
  48. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.erl +393 -0
  49. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_config.hrl +18 -0
  50. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_consult.erl +81 -0
  51. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_decoder.erl +1909 -0
  52. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_encoder.erl +116 -0
  53. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_parser.erl +1214 -0
  54. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_json.erl +408 -0
  55. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_to_term.erl +389 -0
  56. data/service/ssh/ext/ssh_core/local_deps/jsx/src/src/jsx_verify.erl +121 -0
  57. data/service/ssh/ext/ssh_core/rebar.config +24 -0
  58. data/service/ssh/ext/ssh_core/rebar.lock +1 -0
  59. data/service/ssh/ext/ssh_core/src/ssh_auth_engine.erl +156 -0
  60. data/service/ssh/ext/ssh_core/src/ssh_channel_stm.erl +232 -0
  61. data/service/ssh/ext/ssh_core/src/ssh_codec.erl +83 -0
  62. data/service/ssh/ext/ssh_core/src/ssh_conn_sup.erl +48 -0
  63. data/service/ssh/ext/ssh_core/src/ssh_conn_worker.erl +535 -0
  64. data/service/ssh/ext/ssh_core/src/ssh_core.app.src +36 -0
  65. data/service/ssh/ext/ssh_core/src/ssh_core_app.erl +11 -0
  66. data/service/ssh/ext/ssh_core/src/ssh_core_sup.erl +46 -0
  67. data/service/ssh/ext/ssh_core/src/ssh_infra_sup.erl +117 -0
  68. data/service/ssh/ext/ssh_core/src/ssh_ipc.hrl +80 -0
  69. data/service/ssh/ext/ssh_core/src/ssh_ipc_coalesce.erl +94 -0
  70. data/service/ssh/ext/ssh_core/src/ssh_ipc_gateway.erl +467 -0
  71. data/service/ssh/ext/ssh_core/src/ssh_ipc_proto.erl +95 -0
  72. data/service/ssh/ext/ssh_core/src/ssh_jump_chain.erl +101 -0
  73. data/service/ssh/ext/ssh_core/src/ssh_keepalive_mgr.erl +222 -0
  74. data/service/ssh/ext/ssh_core/src/ssh_known_hosts_proxy.erl +67 -0
  75. data/service/ssh/ext/ssh_core/src/ssh_port_fwd.erl +225 -0
  76. data/service/ssh/ext/ssh_core/src/ssh_sftp_session.erl +250 -0
  77. data/service/ssh/ext/ssh_core/src/ssh_sftp_sup.erl +62 -0
  78. data/service/ssh/ext/ssh_core_rs/Cargo.lock +2345 -0
  79. data/service/ssh/ext/ssh_core_rs/Cargo.toml +30 -0
  80. data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs +34 -0
  81. data/service/ssh/ext/ssh_core_rs/bin/ssh_core_rs.cmd +40 -0
  82. data/service/ssh/ext/ssh_core_rs/src/channel.rs +296 -0
  83. data/service/ssh/ext/ssh_core_rs/src/coalesce.rs +143 -0
  84. data/service/ssh/ext/ssh_core_rs/src/codec.rs +71 -0
  85. data/service/ssh/ext/ssh_core_rs/src/conn.rs +628 -0
  86. data/service/ssh/ext/ssh_core_rs/src/gateway.rs +389 -0
  87. data/service/ssh/ext/ssh_core_rs/src/handler.rs +293 -0
  88. data/service/ssh/ext/ssh_core_rs/src/keepalive.rs +194 -0
  89. data/service/ssh/ext/ssh_core_rs/src/main.rs +351 -0
  90. data/service/ssh/ext/ssh_core_rs/src/portfwd.rs +378 -0
  91. data/service/ssh/ext/ssh_core_rs/src/proto.rs +198 -0
  92. data/service/ssh/ext/ssh_core_rs/src/sftp.rs +294 -0
  93. data/service/ssh/lib/network_infra_utility/ssh/automation/macro_engine.rb +213 -0
  94. data/service/ssh/lib/network_infra_utility/ssh/client.rb +257 -0
  95. data/service/ssh/lib/network_infra_utility/ssh/config/schema.rb +90 -0
  96. data/service/ssh/lib/network_infra_utility/ssh/config/settings.rb +103 -0
  97. data/service/ssh/lib/network_infra_utility/ssh/config/store.rb +90 -0
  98. data/service/ssh/lib/network_infra_utility/ssh/ipc/coalesce.rb +83 -0
  99. data/service/ssh/lib/network_infra_utility/ssh/ipc/errors.rb +36 -0
  100. data/service/ssh/lib/network_infra_utility/ssh/ipc/router.rb +212 -0
  101. data/service/ssh/lib/network_infra_utility/ssh/ipc/transport.rb +81 -0
  102. data/service/ssh/lib/network_infra_utility/ssh/security/host_key.rb +211 -0
  103. data/service/ssh/lib/network_infra_utility/ssh/security/vault.rb +211 -0
  104. data/service/ssh/lib/network_infra_utility/ssh/session/history.rb +56 -0
  105. data/service/ssh/lib/network_infra_utility/ssh/session/manager.rb +92 -0
  106. data/service/ssh/lib/network_infra_utility/ssh/session/session.rb +109 -0
  107. data/service/ssh/lib/network_infra_utility/ssh/session/tree.rb +95 -0
  108. data/service/ssh/lib/network_infra_utility/ssh/terminal/ansi_parser.rb +435 -0
  109. data/service/ssh/lib/network_infra_utility/ssh/terminal/buffer.rb +78 -0
  110. data/service/ssh/lib/network_infra_utility/ssh/terminal/emulator.rb +159 -0
  111. data/service/ssh/lib/network_infra_utility/ssh/terminal/logger.rb +195 -0
  112. data/service/ssh/lib/network_infra_utility/ssh/terminal/screen.rb +212 -0
  113. data/service/ssh/lib/network_infra_utility/ssh/terminal/theme.rb +127 -0
  114. data/service/ssh/lib/network_infra_utility/ssh/version.rb +7 -0
  115. data/service/ssh/lib/network_infra_utility/ssh.rb +44 -0
  116. data/support/basic/as_num.rb +221 -0
  117. data/support/basic/mac_address.rb +281 -0
  118. data/version.rb +1 -1
  119. metadata +142 -1
@@ -0,0 +1,506 @@
1
+ %% The MIT License
2
+
3
+ %% Copyright (c) 2010-2013 alisdair sullivan <alisdairsullivan@yahoo.ca>
4
+
5
+ %% Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ %% of this software and associated documentation files (the "Software"), to deal
7
+ %% in the Software without restriction, including without limitation the rights
8
+ %% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ %% copies of the Software, and to permit persons to whom the Software is
10
+ %% furnished to do so, subject to the following conditions:
11
+
12
+ %% The above copyright notice and this permission notice shall be included in
13
+ %% all copies or substantial portions of the Software.
14
+
15
+ %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ %% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ %% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ %% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ %% THE SOFTWARE.
22
+
23
+
24
+ -module(jsx).
25
+
26
+ -export([encode/1, encode/2, decode/1, decode/2]).
27
+ -export([is_json/1, is_json/2, is_term/1, is_term/2]).
28
+ -export([format/1, format/2, minify/1, prettify/1]).
29
+ -export([consult/1, consult/2]).
30
+ -export([encoder/3, decoder/3, parser/3]).
31
+ -export([resume/3]).
32
+
33
+ -export_type([json_term/0, json_text/0, token/0]).
34
+ -export_type([encoder/0, decoder/0, parser/0, internal_state/0]).
35
+ -export_type([config/0]).
36
+
37
+
38
+ -ifdef(TEST).
39
+ %% data and helper functions for tests
40
+ -export([test_cases/0, special_test_cases/0]).
41
+ -export([init/1, handle_event/2]).
42
+ -endif.
43
+
44
+ -type json_term() :: [{binary() | atom(), json_term()}] | [{},...]
45
+ | [json_term()] | []
46
+ | {with_tail, json_term(), binary()}
47
+ | #{ binary() | atom() => json_term() }
48
+ | true | false | null
49
+ | integer() | float()
50
+ | binary() | atom()
51
+ | calendar:datetime().
52
+
53
+ -type json_text() :: binary().
54
+
55
+ -type config() :: jsx_config:config().
56
+
57
+ -spec encode(Source::json_term()) -> json_text() | {incomplete, encoder()}.
58
+
59
+ encode(Source) -> encode(Source, []).
60
+
61
+ -spec encode(Source::json_term(), Config::jsx_config:options()) -> json_text() | {incomplete, encoder()}.
62
+
63
+ encode(Source, Config) -> jsx_to_json:to_json(Source, Config).
64
+
65
+
66
+ -spec decode(Source::json_text()) -> json_term() | {incomplete, decoder()}.
67
+
68
+ decode(Source) -> decode(Source, []).
69
+
70
+ -spec decode(Source::json_text(), Config::jsx_config:options()) -> json_term() | {incomplete, decoder()}.
71
+
72
+ decode(Source, Config) -> jsx_to_term:to_term(Source, Config).
73
+
74
+
75
+ -spec format(Source::json_text()) -> json_text().
76
+
77
+ format(Source) -> format(Source, []).
78
+
79
+ -spec format(Source::json_text(), Config::jsx_config:options()) -> json_text().
80
+
81
+ format(Source, Config) -> jsx_to_json:format(Source, Config).
82
+
83
+
84
+ -spec minify(Source::json_text()) -> json_text().
85
+
86
+ minify(Source) -> format(Source, []).
87
+
88
+
89
+ -spec prettify(Source::json_text()) -> json_text().
90
+
91
+ prettify(Source) -> format(Source, [space, {indent, 2}]).
92
+
93
+
94
+ -spec is_json(Source::binary()) -> boolean() | {incomplete, decoder()}.
95
+
96
+ is_json(Source) -> is_json(Source, []).
97
+
98
+ -spec is_json(Source::binary(), Config::jsx_config:options()) -> boolean() | {incomplete, decoder()}.
99
+
100
+ is_json(Source, Config) -> jsx_verify:is_json(Source, Config).
101
+
102
+
103
+ -spec is_term(Source::json_term() | end_stream | end_json) -> boolean() | {incomplete, encoder()}.
104
+
105
+ is_term(Source) -> is_term(Source, []).
106
+
107
+ -spec is_term(Source::json_term() | end_stream | end_json,
108
+ Config::jsx_config:options()) -> boolean() | {incomplete, encoder()}.
109
+
110
+ is_term(Source, Config) -> jsx_verify:is_term(Source, Config).
111
+
112
+
113
+ -spec consult(File::file:name_all()) -> list(jsx_consult:json_value()).
114
+
115
+ consult(File) -> consult(File, []).
116
+
117
+ -spec consult(File::file:name_all(), Config::jsx_consult:config()) -> list(jsx_consult:json_value()).
118
+
119
+ consult(File, Config) -> jsx_consult:consult(File, Config).
120
+
121
+
122
+ -type decoder() :: fun((json_text() | end_stream | end_json) -> any()).
123
+
124
+ -spec decoder(Handler::module(), State::any(), Config::jsx_config:options()) -> decoder().
125
+
126
+ decoder(Handler, State, Config) -> jsx_decoder:decoder(Handler, State, Config).
127
+
128
+
129
+ -type encoder() :: fun((json_term() | end_stream | end_json) -> any()).
130
+
131
+ -spec encoder(Handler::module(), State::any(), Config::jsx_config:options()) -> encoder().
132
+
133
+ encoder(Handler, State, Config) -> jsx_encoder:encoder(Handler, State, Config).
134
+
135
+
136
+ -type token() :: [token()]
137
+ | start_object
138
+ | end_object
139
+ | start_array
140
+ | end_array
141
+ | {key, binary()}
142
+ | {string, binary()}
143
+ | binary()
144
+ | {number, integer() | float()}
145
+ | {integer, integer()}
146
+ | {float, float()}
147
+ | integer()
148
+ | float()
149
+ | {literal, true}
150
+ | {literal, false}
151
+ | {literal, null}
152
+ | true
153
+ | false
154
+ | null
155
+ | end_json.
156
+
157
+
158
+ -type parser() :: fun((token() | end_stream) -> any()).
159
+
160
+ -spec parser(Handler::module(), State::any(), Config::jsx_config:options()) -> parser().
161
+
162
+ parser(Handler, State, Config) -> jsx_parser:parser(Handler, State, Config).
163
+
164
+ -opaque internal_state() :: tuple().
165
+
166
+ -spec resume(Term::json_text() | token(), InternalState::internal_state(),
167
+ Config::jsx_config:options()) -> jsx:decoder() | {incomplete, jsx:decoder()}.
168
+
169
+ resume(Term, {decoder, State, Handler, Acc, Stack}, Config) ->
170
+ jsx_decoder:resume(Term, State, Handler, Acc, Stack, jsx_config:parse_config(Config));
171
+ resume(Term, {parser, State, Handler, Stack}, Config) ->
172
+ jsx_parser:resume(Term, State, Handler, Stack, jsx_config:parse_config(Config)).
173
+
174
+ -ifdef(TEST).
175
+
176
+ -include_lib("eunit/include/eunit.hrl").
177
+
178
+
179
+ %% test handler
180
+ init([]) -> [].
181
+
182
+ handle_event(end_json, State) -> lists:reverse([end_json] ++ State);
183
+ handle_event(Event, State) -> [Event] ++ State.
184
+
185
+
186
+ test_cases() ->
187
+ empty_array()
188
+ ++ nested_array()
189
+ ++ empty_object()
190
+ ++ nested_object()
191
+ ++ strings()
192
+ ++ literals()
193
+ ++ integers()
194
+ ++ floats()
195
+ ++ compound_object().
196
+
197
+ %% segregate these so we can skip them in `jsx_to_term`
198
+ special_test_cases() -> special_objects() ++ special_array().
199
+
200
+
201
+ empty_array() -> [{"[]", <<"[]">>, [], [start_array, end_array]}].
202
+
203
+
204
+ nested_array() ->
205
+ [{
206
+ "[[[]]]",
207
+ <<"[[[]]]">>,
208
+ [[[]]],
209
+ [start_array, start_array, start_array, end_array, end_array, end_array]
210
+ }].
211
+
212
+
213
+ empty_object() -> [{"{}", <<"{}">>, [{}], [start_object, end_object]}].
214
+
215
+
216
+ nested_object() ->
217
+ [{
218
+ "{\"key\":{\"key\":{}}}",
219
+ <<"{\"key\":{\"key\":{}}}">>,
220
+ [{<<"key">>, [{<<"key">>, [{}]}]}],
221
+ [
222
+ start_object,
223
+ {key, <<"key">>},
224
+ start_object,
225
+ {key, <<"key">>},
226
+ start_object,
227
+ end_object,
228
+ end_object,
229
+ end_object
230
+ ]
231
+ }].
232
+
233
+
234
+ naked_strings() ->
235
+ Raw = [
236
+ "",
237
+ "hello world"
238
+ ],
239
+ [
240
+ {
241
+ String,
242
+ <<"\"", (list_to_binary(String))/binary, "\"">>,
243
+ list_to_binary(String),
244
+ [{string, list_to_binary(String)}]
245
+ }
246
+ || String <- Raw
247
+ ].
248
+
249
+
250
+ strings() ->
251
+ naked_strings()
252
+ ++ [ wrap_with_array(Test) || Test <- naked_strings() ]
253
+ ++ [ wrap_with_object(Test) || Test <- naked_strings() ].
254
+
255
+
256
+ naked_integers() ->
257
+ Raw = [
258
+ 1, 2, 3,
259
+ 127, 128, 129,
260
+ 255, 256, 257,
261
+ 65534, 65535, 65536,
262
+ 18446744073709551616,
263
+ 18446744073709551617
264
+ ],
265
+ [
266
+ {
267
+ integer_to_list(X),
268
+ list_to_binary(integer_to_list(X)),
269
+ X,
270
+ [{integer, X}]
271
+ }
272
+ || X <- Raw ++ [ -1 * Y || Y <- Raw ] ++ [0]
273
+ ].
274
+
275
+
276
+ integers() ->
277
+ naked_integers()
278
+ ++ [ wrap_with_array(Test) || Test <- naked_integers() ]
279
+ ++ [ wrap_with_object(Test) || Test <- naked_integers() ].
280
+
281
+
282
+ naked_floats() ->
283
+ Raw = [
284
+ 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9,
285
+ 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9,
286
+ 1234567890.0987654321,
287
+ 0.0e0,
288
+ 1234567890.0987654321e16,
289
+ 0.1e0, 0.1e1, 0.1e2, 0.1e4, 0.1e8, 0.1e16, 0.1e308,
290
+ 1.0e0, 1.0e1, 1.0e2, 1.0e4, 1.0e8, 1.0e16, 1.0e308,
291
+ 2.2250738585072014e-308, %% min normalized float
292
+ 1.7976931348623157e308, %% max normalized float
293
+ 5.0e-324, %% min denormalized float
294
+ 2.225073858507201e-308 %% max denormalized float
295
+ ],
296
+ [
297
+ {
298
+ sane_float_to_list(X),
299
+ list_to_binary(sane_float_to_list(X)),
300
+ X,
301
+ [{float, X}]
302
+ }
303
+ || X <- Raw ++ [ -1 * Y || Y <- Raw ]
304
+ ].
305
+
306
+
307
+ floats() ->
308
+ naked_floats()
309
+ ++ [ wrap_with_array(Test) || Test <- naked_floats() ]
310
+ ++ [ wrap_with_object(Test) || Test <- naked_floats() ].
311
+
312
+
313
+ naked_literals() ->
314
+ [
315
+ {
316
+ atom_to_list(Literal),
317
+ atom_to_binary(Literal, unicode),
318
+ Literal,
319
+ [{literal, Literal}]
320
+ }
321
+ || Literal <- [true, false, null]
322
+ ].
323
+
324
+
325
+ literals() ->
326
+ naked_literals()
327
+ ++ [ wrap_with_array(Test) || Test <- naked_literals() ]
328
+ ++ [ wrap_with_object(Test) || Test <- naked_literals() ].
329
+
330
+
331
+ compound_object() ->
332
+ [{
333
+ "[{\"alpha\":[1,2,3],\"beta\":{\"alpha\":[1.0,2.0,3.0],\"beta\":[true,false]}},[{}]]",
334
+ <<"[{\"alpha\":[1,2,3],\"beta\":{\"alpha\":[1.0,2.0,3.0],\"beta\":[true,false]}},[{}]]">>,
335
+ [[{<<"alpha">>, [1, 2, 3]}, {<<"beta">>, [{<<"alpha">>, [1.0, 2.0, 3.0]}, {<<"beta">>, [true, false]}]}], [[{}]]],
336
+ [
337
+ start_array,
338
+ start_object,
339
+ {key, <<"alpha">>},
340
+ start_array,
341
+ {integer, 1},
342
+ {integer, 2},
343
+ {integer, 3},
344
+ end_array,
345
+ {key, <<"beta">>},
346
+ start_object,
347
+ {key, <<"alpha">>},
348
+ start_array,
349
+ {float, 1.0},
350
+ {float, 2.0},
351
+ {float, 3.0},
352
+ end_array,
353
+ {key, <<"beta">>},
354
+ start_array,
355
+ {literal, true},
356
+ {literal, false},
357
+ end_array,
358
+ end_object,
359
+ end_object,
360
+ start_array,
361
+ start_object,
362
+ end_object,
363
+ end_array,
364
+ end_array
365
+ ]
366
+ }].
367
+
368
+
369
+ special_objects() ->
370
+ [
371
+ {
372
+ "[{key, atom}]",
373
+ <<"{\"key\":\"atom\"}">>,
374
+ [{key, atom}],
375
+ [start_object, {key, <<"key">>}, {string, <<"atom">>}, end_object]
376
+ },
377
+ {
378
+ "[{1, true}]",
379
+ <<"{\"1\":true}">>,
380
+ [{1, true}],
381
+ [start_object, {key, <<"1">>}, {literal, true}, end_object]
382
+ }
383
+ ].
384
+
385
+
386
+ special_array() ->
387
+ [
388
+ {
389
+ "[foo, bar]",
390
+ <<"[\"foo\",\"bar\"]">>,
391
+ [foo, bar],
392
+ [start_array, {string, <<"foo">>}, {string, <<"bar">>}, end_array]
393
+ }
394
+ ].
395
+
396
+
397
+ wrap_with_array({Title, JSON, Term, Events}) ->
398
+ {
399
+ "[" ++ Title ++ "]",
400
+ <<"[", JSON/binary, "]">>,
401
+ [Term],
402
+ [start_array] ++ Events ++ [end_array]
403
+ }.
404
+
405
+
406
+ wrap_with_object({Title, JSON, Term, Events}) ->
407
+ {
408
+ "{\"key\":" ++ Title ++ "}",
409
+ <<"{\"key\":", JSON/binary, "}">>,
410
+ [{<<"key">>, Term}],
411
+ [start_object, {key, <<"key">>}] ++ Events ++ [end_object]
412
+ }.
413
+
414
+
415
+ sane_float_to_list(X) ->
416
+ [Output] = io_lib:format("~p", [X]),
417
+ Output.
418
+
419
+
420
+ incremental_decode(JSON) ->
421
+ Final = lists:foldl(
422
+ fun(Byte, Decoder) -> {incomplete, F} = Decoder(Byte), F end,
423
+ decoder(jsx, [], [stream]),
424
+ json_to_bytes(JSON)
425
+ ),
426
+ Final(end_stream).
427
+
428
+
429
+ incremental_parse(Events) ->
430
+ Final = lists:foldl(
431
+ fun(Event, Parser) -> {incomplete, F} = Parser(Event), F end,
432
+ parser(?MODULE, [], [stream]),
433
+ lists:map(fun(X) -> [X] end, Events)
434
+ ),
435
+ Final(end_stream).
436
+
437
+
438
+ %% used to convert a json text into a list of codepoints to be incrementally
439
+ %% parsed
440
+ json_to_bytes(JSON) -> json_to_bytes(JSON, []).
441
+
442
+ json_to_bytes(<<>>, Acc) -> [<<>>] ++ lists:reverse(Acc);
443
+ json_to_bytes(<<X, Rest/binary>>, Acc) -> json_to_bytes(Rest, [<<X>>] ++ Acc).
444
+
445
+
446
+ %% actual tests!
447
+ decode_test_() ->
448
+ Data = test_cases(),
449
+ [{Title, ?_assertEqual(Events ++ [end_json], (decoder(?MODULE, [], []))(JSON))}
450
+ || {Title, JSON, _, Events} <- Data
451
+ ] ++
452
+ [{Title ++ " (incremental)", ?_assertEqual(Events ++ [end_json], incremental_decode(JSON))}
453
+ || {Title, JSON, _, Events} <- Data
454
+ ].
455
+
456
+
457
+ parse_test_() ->
458
+ Data = test_cases(),
459
+ [{Title, ?_assertEqual(Events ++ [end_json], (parser(?MODULE, [], []))(Events ++ [end_json]))}
460
+ || {Title, _, _, Events} <- Data
461
+ ] ++
462
+ [{Title ++ " (incremental)", ?_assertEqual(Events ++ [end_json], incremental_parse(Events))}
463
+ || {Title, _, _, Events} <- Data
464
+ ].
465
+
466
+
467
+ encode_test_() ->
468
+ Data = test_cases(),
469
+ [
470
+ {
471
+ Title, ?_assertEqual(
472
+ Events ++ [end_json],
473
+ (jsx:encoder(jsx, [], []))(Term)
474
+ )
475
+ } || {Title, _, Term, Events} <- Data
476
+ ].
477
+
478
+ end_stream_test_() ->
479
+ Tokens = [start_object, end_object, end_json],
480
+ [
481
+ {"encoder end_stream", ?_assertEqual(
482
+ Tokens,
483
+ begin
484
+ {incomplete, F} = (jsx:parser(jsx, [], [stream]))([start_object, end_object]),
485
+ F(end_stream)
486
+ end
487
+ )},
488
+ {"encoder end_json", ?_assertEqual(
489
+ Tokens,
490
+ begin
491
+ {incomplete, F} = (jsx:parser(jsx, [], [stream]))([start_object, end_object]),
492
+ F(end_json)
493
+ end
494
+ )},
495
+ {"decoder end_stream", ?_assertEqual(
496
+ Tokens,
497
+ begin {incomplete, F} = (jsx:decoder(jsx, [], [stream]))(<<"{}">>), F(end_stream) end
498
+ )},
499
+ {"decoder end_json", ?_assertEqual(
500
+ Tokens,
501
+ begin {incomplete, F} = (jsx:decoder(jsx, [], [stream]))(<<"{}">>), F(end_json) end
502
+ )}
503
+ ].
504
+
505
+
506
+ -endif.