iodine 0.7.59 → 0.8.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 (160) hide show
  1. checksums.yaml +4 -4
  2. data/.clang-format +15 -0
  3. data/.rspec +1 -0
  4. data/.yardopts +1 -3
  5. data/CHANGELOG.md +132 -12
  6. data/Gemfile +5 -7
  7. data/LICENSE.txt +1 -1
  8. data/README.md +147 -671
  9. data/Rakefile +9 -16
  10. data/examples/chatroom.nru +9 -0
  11. data/examples/client +74 -0
  12. data/examples/config-hello.nru +9 -0
  13. data/examples/config-hello.ru +11 -0
  14. data/examples/config-hijack.ru +13 -0
  15. data/examples/config-shootout.ru +43 -0
  16. data/examples/config.nru +120 -0
  17. data/examples/config.rb +37 -0
  18. data/examples/config.ru +42 -53
  19. data/examples/fake +24 -0
  20. data/examples/hello_neorack +137 -0
  21. data/examples/routes.nru +29 -0
  22. data/examples/routes.ru +42 -0
  23. data/exe/iodine +218 -258
  24. data/ext/iodine/extconf.rb +27 -100
  25. data/ext/iodine/fio-stl.h +128336 -0
  26. data/ext/iodine/fio-stl.md +26396 -0
  27. data/ext/iodine/iodine.c +213 -1393
  28. data/ext/iodine/iodine.h +250 -55
  29. data/ext/iodine/iodine_arg_helper.h +329 -0
  30. data/ext/iodine/iodine_caller.h +234 -25
  31. data/ext/iodine/iodine_cli.h +434 -0
  32. data/ext/iodine/iodine_compression.h +312 -0
  33. data/ext/iodine/iodine_connection.h +3484 -34
  34. data/ext/iodine/iodine_core.h +363 -0
  35. data/ext/iodine/iodine_crypto.h +1441 -0
  36. data/ext/iodine/iodine_defer.h +225 -4
  37. data/ext/iodine/iodine_json.h +738 -4
  38. data/ext/iodine/iodine_listener.h +263 -0
  39. data/ext/iodine/iodine_log.h +297 -0
  40. data/ext/iodine/iodine_minimap.h +543 -0
  41. data/ext/iodine/iodine_mustache.h +461 -4
  42. data/ext/iodine/iodine_pubsub_eng.h +729 -0
  43. data/ext/iodine/iodine_pubsub_history.h +547 -0
  44. data/ext/iodine/iodine_pubsub_msg.h +228 -0
  45. data/ext/iodine/iodine_redis.h +322 -0
  46. data/ext/iodine/iodine_store.h +418 -16
  47. data/ext/iodine/iodine_threads.h +279 -0
  48. data/ext/iodine/iodine_tls.h +515 -6
  49. data/ext/iodine/iodine_utils.h +923 -0
  50. data/iodine.gemspec +37 -42
  51. data/lib/iodine/benchmark.rb +1690 -0
  52. data/lib/iodine/documentation.rb +3085 -0
  53. data/lib/iodine/version.rb +17 -1
  54. data/lib/iodine.rb +54 -255
  55. data/logo.svg +36 -0
  56. data/mustache.md +55 -0
  57. data/sig/iodine.rbs +4 -0
  58. metadata +58 -184
  59. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -40
  60. data/.github/workflows/ruby.yml +0 -42
  61. data/.gitignore +0 -20
  62. data/LIMITS.md +0 -41
  63. data/SPEC-PubSub-Draft.md +0 -159
  64. data/SPEC-WebSocket-Draft.md +0 -239
  65. data/bin/console +0 -22
  66. data/bin/info.md +0 -353
  67. data/bin/mustache_bench.rb +0 -100
  68. data/bin/poc/Gemfile.lock +0 -23
  69. data/bin/poc/README.md +0 -37
  70. data/bin/poc/config.ru +0 -66
  71. data/bin/poc/gemfile +0 -1
  72. data/bin/poc/www/index.html +0 -57
  73. data/examples/async_task.ru +0 -92
  74. data/examples/bates/README.md +0 -3
  75. data/examples/bates/config.ru +0 -342
  76. data/examples/bates/david+bold.pdf +0 -0
  77. data/examples/bates/public/drop-pdf.png +0 -0
  78. data/examples/bates/public/index.html +0 -600
  79. data/examples/echo.ru +0 -59
  80. data/examples/etag.ru +0 -16
  81. data/examples/hello.ru +0 -29
  82. data/examples/pubsub_engine.ru +0 -81
  83. data/examples/rack3.ru +0 -12
  84. data/examples/redis.ru +0 -70
  85. data/examples/shootout.ru +0 -73
  86. data/examples/sub-protocols.ru +0 -90
  87. data/examples/tcp_client.rb +0 -66
  88. data/examples/x-sendfile.ru +0 -14
  89. data/ext/iodine/fio.c +0 -11995
  90. data/ext/iodine/fio.h +0 -6371
  91. data/ext/iodine/fio_cli.c +0 -431
  92. data/ext/iodine/fio_cli.h +0 -189
  93. data/ext/iodine/fio_json_parser.h +0 -688
  94. data/ext/iodine/fio_siphash.c +0 -157
  95. data/ext/iodine/fio_siphash.h +0 -37
  96. data/ext/iodine/fio_tls.h +0 -129
  97. data/ext/iodine/fio_tls_missing.c +0 -649
  98. data/ext/iodine/fio_tls_openssl.c +0 -1106
  99. data/ext/iodine/fio_tmpfile.h +0 -50
  100. data/ext/iodine/fiobj.h +0 -44
  101. data/ext/iodine/fiobj4fio.h +0 -21
  102. data/ext/iodine/fiobj_ary.c +0 -333
  103. data/ext/iodine/fiobj_ary.h +0 -139
  104. data/ext/iodine/fiobj_data.c +0 -1187
  105. data/ext/iodine/fiobj_data.h +0 -167
  106. data/ext/iodine/fiobj_hash.c +0 -409
  107. data/ext/iodine/fiobj_hash.h +0 -176
  108. data/ext/iodine/fiobj_json.c +0 -622
  109. data/ext/iodine/fiobj_json.h +0 -68
  110. data/ext/iodine/fiobj_mem.h +0 -71
  111. data/ext/iodine/fiobj_mustache.c +0 -317
  112. data/ext/iodine/fiobj_mustache.h +0 -62
  113. data/ext/iodine/fiobj_numbers.c +0 -344
  114. data/ext/iodine/fiobj_numbers.h +0 -127
  115. data/ext/iodine/fiobj_str.c +0 -433
  116. data/ext/iodine/fiobj_str.h +0 -172
  117. data/ext/iodine/fiobject.c +0 -620
  118. data/ext/iodine/fiobject.h +0 -655
  119. data/ext/iodine/hpack.h +0 -1923
  120. data/ext/iodine/http.c +0 -2743
  121. data/ext/iodine/http.h +0 -1002
  122. data/ext/iodine/http1.c +0 -910
  123. data/ext/iodine/http1.h +0 -29
  124. data/ext/iodine/http1_parser.h +0 -878
  125. data/ext/iodine/http_internal.c +0 -1279
  126. data/ext/iodine/http_internal.h +0 -237
  127. data/ext/iodine/http_mime_parser.h +0 -350
  128. data/ext/iodine/iodine_caller.c +0 -230
  129. data/ext/iodine/iodine_connection.c +0 -941
  130. data/ext/iodine/iodine_defer.c +0 -420
  131. data/ext/iodine/iodine_fiobj2rb.h +0 -120
  132. data/ext/iodine/iodine_helpers.c +0 -282
  133. data/ext/iodine/iodine_helpers.h +0 -12
  134. data/ext/iodine/iodine_http.c +0 -1181
  135. data/ext/iodine/iodine_http.h +0 -23
  136. data/ext/iodine/iodine_json.c +0 -302
  137. data/ext/iodine/iodine_mustache.c +0 -567
  138. data/ext/iodine/iodine_pubsub.c +0 -580
  139. data/ext/iodine/iodine_pubsub.h +0 -26
  140. data/ext/iodine/iodine_rack_io.c +0 -273
  141. data/ext/iodine/iodine_rack_io.h +0 -20
  142. data/ext/iodine/iodine_store.c +0 -146
  143. data/ext/iodine/iodine_tcp.c +0 -346
  144. data/ext/iodine/iodine_tcp.h +0 -13
  145. data/ext/iodine/iodine_tls.c +0 -261
  146. data/ext/iodine/mustache_parser.h +0 -1546
  147. data/ext/iodine/redis_engine.c +0 -957
  148. data/ext/iodine/redis_engine.h +0 -79
  149. data/ext/iodine/resp_parser.h +0 -317
  150. data/ext/iodine/websocket_parser.h +0 -506
  151. data/ext/iodine/websockets.c +0 -743
  152. data/ext/iodine/websockets.h +0 -185
  153. data/lib/iodine/connection.rb +0 -61
  154. data/lib/iodine/json.rb +0 -42
  155. data/lib/iodine/mustache.rb +0 -113
  156. data/lib/iodine/pubsub.rb +0 -55
  157. data/lib/iodine/rack_utils.rb +0 -43
  158. data/lib/iodine/tls.rb +0 -16
  159. data/lib/rack/handler/iodine.rb +0 -33
  160. data/logo.png +0 -0
@@ -1,567 +0,0 @@
1
- #include <ruby.h>
2
- #define INCLUDE_MUSTACHE_IMPLEMENTATION 1
3
- #include "mustache_parser.h"
4
-
5
- #include "iodine.h"
6
-
7
- #define FIO_INCLUDE_STR
8
- #include <fio.h>
9
-
10
- static ID call_func_id;
11
- static VALUE filename_id;
12
- static VALUE data_id;
13
- static VALUE template_id;
14
- /* *****************************************************************************
15
- C <=> Ruby Data allocation
16
- ***************************************************************************** */
17
-
18
- static size_t iodine_mustache_data_size(const void *c_) {
19
- return sizeof(mustache_s *) +
20
- (((mustache_s **)c_)[0]
21
- ? (((mustache_s **)c_)[0]->u.read_only.data_length +
22
- (((mustache_s **)c_)[0]->u.read_only.intruction_count *
23
- sizeof(struct mustache__instruction_s)))
24
- : 0);
25
- (void)c_;
26
- }
27
-
28
- static void iodine_mustache_data_free(void *c_) {
29
- mustache_free(((mustache_s **)c_)[0]);
30
- FIO_LOG_DEBUG("deallocated mustache data at: %p", ((void **)c_)[0]);
31
- free((void *)c_);
32
- FIO_LOG_DEBUG("deallocated mustache pointer at: %p", c_);
33
- (void)c_;
34
- }
35
-
36
- static const rb_data_type_t iodine_mustache_data_type = {
37
- .wrap_struct_name = "IodineMustacheData",
38
- .function =
39
- {
40
- .dmark = NULL,
41
- .dfree = iodine_mustache_data_free,
42
- .dsize = iodine_mustache_data_size,
43
- },
44
- .data = NULL,
45
- // .flags = RUBY_TYPED_FREE_IMMEDIATELY,
46
- };
47
-
48
- /* Iodine::PubSub::Engine.allocate */
49
- static VALUE iodine_mustache_data_alloc_c(VALUE self) {
50
- void *m = malloc(sizeof(mustache_s *));
51
- ((mustache_s **)m)[0] = NULL;
52
- FIO_LOG_DEBUG("allocated mustache pointer at: %p", m);
53
- return TypedData_Wrap_Struct(self, &iodine_mustache_data_type, m);
54
- }
55
-
56
- /* *****************************************************************************
57
- Parser Callbacks
58
- ***************************************************************************** */
59
-
60
- static inline VALUE fiobj_mustache_find_obj_absolute(VALUE udata,
61
- const char *name,
62
- uint32_t name_len) {
63
- VALUE tmp;
64
- if (!RB_TYPE_P(udata, T_HASH)) {
65
- if (name_len == 1 && name[0] == '.')
66
- return udata;
67
- /* search by method */
68
- ID name_id = rb_intern2(name, name_len);
69
- if (rb_respond_to(udata, name_id)) {
70
- return IodineCaller.call(udata, name_id);
71
- }
72
- return Qnil;
73
- }
74
- /* search by Symbol */
75
- ID name_id = rb_intern2(name, name_len);
76
- VALUE key = ID2SYM(name_id);
77
- tmp = rb_hash_lookup2(udata, key, Qundef);
78
- if (tmp != Qundef)
79
- return tmp;
80
- /* search by String */
81
- key = rb_sym2str(key);
82
- tmp = rb_hash_lookup2(udata, key, Qundef);
83
- rb_str_free(key);
84
- if (tmp != Qundef)
85
- return tmp;
86
- /* search by method */
87
- tmp = Qnil;
88
- if (rb_respond_to(udata, name_id)) {
89
- tmp = IodineCaller.call(udata, name_id);
90
- }
91
-
92
- return tmp;
93
- }
94
-
95
- static inline VALUE fiobj_mustache_find_obj_tree(mustache_section_s *section,
96
- const char *name,
97
- uint32_t name_len) {
98
- do {
99
- VALUE tmp = fiobj_mustache_find_obj_absolute((VALUE)section->udata2, name,
100
- name_len);
101
- if (tmp != Qnil) {
102
- return tmp;
103
- }
104
- } while ((section = mustache_section_parent(section)));
105
- return Qnil;
106
- }
107
-
108
- static inline VALUE fiobj_mustache_find_obj(mustache_section_s *section,
109
- const char *name,
110
- uint32_t name_len) {
111
- VALUE tmp = fiobj_mustache_find_obj_tree(section, name, name_len);
112
- if (tmp != Qnil)
113
- return tmp;
114
- /* interpolate sections... */
115
- uint32_t dot = 0;
116
- while (dot < name_len && name[dot] != '.')
117
- ++dot;
118
- if (dot == name_len)
119
- return Qnil;
120
- tmp = fiobj_mustache_find_obj_tree(section, name, dot);
121
- if (!tmp) {
122
- return Qnil;
123
- }
124
- ++dot;
125
- for (;;) {
126
- VALUE obj =
127
- fiobj_mustache_find_obj_absolute(tmp, name + dot, name_len - dot);
128
- if (obj != Qnil)
129
- return obj;
130
- name += dot;
131
- name_len -= dot;
132
- dot = 0;
133
- while (dot < name_len && name[dot] != '.')
134
- ++dot;
135
- if (dot == name_len) {
136
- return Qnil;
137
- }
138
- tmp = fiobj_mustache_find_obj_absolute(tmp, name, dot);
139
- if (tmp == Qnil)
140
- return Qnil;
141
- ++dot;
142
- }
143
- }
144
- /**
145
- * Called when an argument name was detected in the current section.
146
- *
147
- * A conforming implementation will search for the named argument both in the
148
- * existing section and all of it's parents (walking backwards towards the root)
149
- * until a value is detected.
150
- *
151
- * A missing value should be treated the same as an empty string.
152
- *
153
- * A conforming implementation will output the named argument's value (either
154
- * HTML escaped or not, depending on the `escape` flag) as a string.
155
- */
156
- static int mustache_on_arg(mustache_section_s *section, const char *name,
157
- uint32_t name_len, unsigned char escape) {
158
- VALUE o = fiobj_mustache_find_obj(section, name, name_len);
159
- switch (o) {
160
- case Qnil:
161
- case Qfalse:
162
- return 0;
163
- case Qtrue:
164
- fio_str_write(section->udata1, "true", 4);
165
- break;
166
- }
167
- if (!RB_TYPE_P(o, T_STRING)) {
168
- if (rb_respond_to(o, call_func_id))
169
- o = IodineCaller.call(o, call_func_id);
170
- if (!RB_TYPE_P(o, T_STRING))
171
- o = IodineCaller.call(o, iodine_to_s_id);
172
- }
173
- if (!RB_TYPE_P(o, T_STRING) || !RSTRING_LEN(o))
174
- return 0;
175
- return mustache_write_text(section, RSTRING_PTR(o), RSTRING_LEN(o), escape);
176
- }
177
-
178
- /**
179
- * Called when simple template text (string) is detected.
180
- *
181
- * A conforming implementation will output data as a string (no escaping).
182
- */
183
- static int mustache_on_text(mustache_section_s *section, const char *data,
184
- uint32_t data_len) {
185
- fio_str_write(section->udata1, data, data_len);
186
- return 0;
187
- }
188
-
189
- /**
190
- * Called for nested sections, must return the number of objects in the new
191
- * subsection (depending on the argument's name).
192
- *
193
- * Arrays should return the number of objects in the array.
194
- *
195
- * `true` values should return 1.
196
- *
197
- * `false` values should return 0.
198
- *
199
- * A return value of -1 will stop processing with an error.
200
- *
201
- * Please note, this will handle both normal and inverted sections.
202
- */
203
- static int32_t mustache_on_section_test(mustache_section_s *section,
204
- const char *name, uint32_t name_len,
205
- uint8_t callable) {
206
- VALUE o = fiobj_mustache_find_obj(section, name, name_len);
207
- if (o == Qnil || o == Qfalse) {
208
- return 0;
209
- }
210
- if (RB_TYPE_P(o, T_ARRAY)) {
211
- return RARRAY_LEN(o);
212
- }
213
- if (callable && rb_respond_to(o, call_func_id)) {
214
- size_t len;
215
- const char *txt = mustache_section_text(section, &len);
216
- VALUE str = Qnil;
217
- if (txt && len) {
218
- str = rb_str_new(txt, len);
219
- }
220
- o = IodineCaller.call2(o, call_func_id, 1, &str);
221
- if (!RB_TYPE_P(o, T_STRING))
222
- o = rb_funcall2(o, iodine_to_s_id, 0, NULL);
223
- if (RB_TYPE_P(o, T_STRING) && RSTRING_LEN(o))
224
- mustache_write_text(section, RSTRING_PTR(o), RSTRING_LEN(o), 0);
225
- return 0;
226
- }
227
- return 1;
228
- }
229
-
230
- /**
231
- * Called when entering a nested section.
232
- *
233
- * `index` is a zero based index indicating the number of repetitions that
234
- * occurred so far (same as the array index for arrays).
235
- *
236
- * A return value of -1 will stop processing with an error.
237
- *
238
- * Note: this is a good time to update the subsection's `udata` with the value
239
- * of the array index. The `udata` will always contain the value or the parent's
240
- * `udata`.
241
- */
242
- static int mustache_on_section_start(mustache_section_s *section,
243
- char const *name, uint32_t name_len,
244
- uint32_t index) {
245
- VALUE o = fiobj_mustache_find_obj(section, name, name_len);
246
- if (RB_TYPE_P(o, T_ARRAY))
247
- section->udata2 = (void *)rb_ary_entry(o, index);
248
- else if (RB_TYPE_P(o, T_HASH))
249
- section->udata2 = (void *)o;
250
- return 0;
251
- }
252
-
253
- /**
254
- * Called for cleanup in case of error.
255
- */
256
- static void mustache_on_formatting_error(void *udata1, void *udata2) {
257
- (void)udata1;
258
- (void)udata2;
259
- }
260
-
261
- /* *****************************************************************************
262
- Loading the template
263
- ***************************************************************************** */
264
-
265
- /**
266
- Loads the mustache template found in `:filename`. If `:template` is provided it
267
- will be used instead of reading the file's content.
268
-
269
- Iodine::Mustache.new(filename, template = nil)
270
-
271
- When template data is provided, filename (if any) will only be used for partial
272
- template path resolution and the template data will be used for the template's
273
- content. This allows, for example, for front matter to be extracted before
274
- parsing the template.
275
-
276
- Once a template was loaded, it could be rendered using {render}.
277
-
278
- Accepts named arguments as well:
279
-
280
- Iodine::Mustache.new(filename: "foo.mustache", template: "{{ bar }}")
281
-
282
- */
283
- static VALUE iodine_mustache_new(int argc, VALUE *argv, VALUE self) {
284
- VALUE filename = Qnil, template = Qnil;
285
- if (argc == 1 && RB_TYPE_P(argv[0], T_HASH)) {
286
- /* named arguments */
287
- filename = rb_hash_aref(argv[0], filename_id);
288
- template = rb_hash_aref(argv[0], template_id);
289
- } else {
290
- /* regular arguments */
291
- if (argc == 0 || argc > 2)
292
- rb_raise(rb_eArgError, "expecting 1..2 arguments or named arguments.");
293
- filename = argv[0];
294
- if (argc > 1) {
295
- template = argv[1];
296
- }
297
- }
298
- if (filename == Qnil && template == Qnil)
299
- rb_raise(rb_eArgError, "need either template contents or file name.");
300
-
301
- if (template != Qnil)
302
- Check_Type(template, T_STRING);
303
- if (filename != Qnil)
304
- Check_Type(filename, T_STRING);
305
-
306
- mustache_s **m = NULL;
307
- TypedData_Get_Struct(self, mustache_s *, &iodine_mustache_data_type, m);
308
- if (!m) {
309
- rb_raise(rb_eRuntimeError, "Iodine::Mustache allocation error.");
310
- }
311
-
312
- mustache_error_en err;
313
- *m = mustache_load(.filename =
314
- (filename == Qnil ? NULL : RSTRING_PTR(filename)),
315
- .filename_len =
316
- (filename == Qnil ? 0 : RSTRING_LEN(filename)),
317
- .data = (template == Qnil ? NULL : RSTRING_PTR(template)),
318
- .data_len = (template == Qnil ? 0 : RSTRING_LEN(template)),
319
- .err = &err);
320
- if (!*m)
321
- goto error;
322
-
323
- FIO_LOG_DEBUG("allocated / loaded mustache data at: %p", (void *)*m);
324
-
325
- return self;
326
- error:
327
- switch (err) {
328
- case MUSTACHE_OK:
329
- rb_raise(rb_eRuntimeError, "Iodine::Mustache template ok, unknown error.");
330
- break;
331
- case MUSTACHE_ERR_TOO_DEEP:
332
- rb_raise(rb_eRuntimeError, "Iodine::Mustache element nesting too deep.");
333
- break;
334
- case MUSTACHE_ERR_CLOSURE_MISMATCH:
335
- rb_raise(rb_eRuntimeError,
336
- "Iodine::Mustache template error, closure mismatch.");
337
- break;
338
- case MUSTACHE_ERR_FILE_NOT_FOUND:
339
- rb_raise(rb_eLoadError, "Iodine::Mustache template not found.");
340
- break;
341
- case MUSTACHE_ERR_FILE_TOO_BIG:
342
- rb_raise(rb_eLoadError, "Iodine::Mustache template too big.");
343
- break;
344
- case MUSTACHE_ERR_FILE_NAME_TOO_LONG:
345
- rb_raise(rb_eRuntimeError, "Iodine::Mustache template name too long.");
346
- break;
347
- case MUSTACHE_ERR_EMPTY_TEMPLATE:
348
- rb_raise(rb_eRuntimeError, "Iodine::Mustache template is empty.");
349
- break;
350
- case MUSTACHE_ERR_UNKNOWN:
351
- rb_raise(rb_eRuntimeError, "Iodine::Mustache unknown error.");
352
- break;
353
- case MUSTACHE_ERR_USER_ERROR:
354
- rb_raise(rb_eRuntimeError, "Iodine::Mustache internal error.");
355
- break;
356
- case MUSTACHE_ERR_FILE_NAME_TOO_SHORT:
357
- rb_raise(rb_eRuntimeError, "Iodine::Mustache template file name too long.");
358
-
359
- break;
360
- case MUSTACHE_ERR_DELIMITER_TOO_LONG:
361
- rb_raise(rb_eRuntimeError, "Iodine::Mustache new delimiter is too long.");
362
-
363
- break;
364
- case MUSTACHE_ERR_NAME_TOO_LONG:
365
- rb_raise(rb_eRuntimeError,
366
- "Iodine::Mustache section name in template is too long.");
367
- default:
368
- break;
369
- }
370
- return self;
371
- }
372
-
373
- /* *****************************************************************************
374
- Rendering
375
- ***************************************************************************** */
376
-
377
- /**
378
- Renders the mustache template using the data provided in the `data` argument.
379
-
380
- Returns a String with the rendered template.
381
-
382
- Raises an exception on error.
383
-
384
- NOTE:
385
-
386
- As one might notice, no binding is provided. Instead, a `data` Hash is assumed.
387
- Iodine will search the Hash for any data while protecting against code
388
- execution.
389
- */
390
- static VALUE iodine_mustache_render(VALUE self, VALUE data) {
391
- fio_str_s str = FIO_STR_INIT;
392
- mustache_s **m = NULL;
393
- TypedData_Get_Struct(self, mustache_s *, &iodine_mustache_data_type, m);
394
- if (!m) {
395
- rb_raise(rb_eRuntimeError, "Iodine::Mustache allocation error.");
396
- }
397
- if (mustache_build(*m, .udata1 = &str, .udata2 = (void *)data))
398
- goto error;
399
- fio_str_info_s i = fio_str_info(&str);
400
- VALUE ret = rb_str_new(i.data, i.len);
401
- fio_str_free(&str);
402
- return ret;
403
-
404
- error:
405
- fio_str_free(&str);
406
- rb_raise(rb_eRuntimeError, "Couldn't build template frome data.");
407
- }
408
-
409
- /**
410
- Renders the mustache template found in `filename`, using the data provided in
411
- the `data` argument. If `template` is provided it will be used instead of
412
- reading the file's content.
413
-
414
- Iodine::Mustache.render(filename, data, template = nil)
415
-
416
- Returns a String with the rendered template.
417
-
418
- Raises an exception on error.
419
-
420
- template = "<h1>{{title}}</h1>"
421
- filename = "templates/index"
422
- data = {title: "Home"}
423
- result = Iodine::Mustache.render(filename, data)
424
-
425
- # filename will be used to resolve the path to any partials:
426
- result = Iodine::Mustache.render(filename, data, template)
427
-
428
- # OR, if we don't need partial template path resolution
429
- result = Iodine::Mustache.render(template: template, data: data)
430
-
431
- NOTE 1:
432
-
433
- This function doesn't cache the template data.
434
-
435
- The more complext the template the higher the cost of the template parsing
436
- stage.
437
-
438
- Consider creating a persistent template object using a new object and using the
439
- instance {#render} method.
440
-
441
- NOTE 2:
442
-
443
- As one might notice, no binding is provided. Instead, a `data` Hash is assumed.
444
- Iodine will search the Hash for any data while protecting against code
445
- execution.
446
- */
447
- static VALUE iodine_mustache_render_klass(int argc, VALUE *argv, VALUE self) {
448
- VALUE filename = Qnil, data = Qnil, template = Qnil;
449
- if (argc == 1) {
450
- /* named arguments */
451
- Check_Type(argv[0], T_HASH);
452
- filename = rb_hash_aref(argv[0], filename_id);
453
- data = rb_hash_aref(argv[0], data_id);
454
- template = rb_hash_aref(argv[0], template_id);
455
- } else {
456
- /* regular arguments */
457
- if (argc < 2 || argc > 3)
458
- rb_raise(rb_eArgError, "expecting 2..3 arguments or named arguments.");
459
- filename = argv[0];
460
- data = argv[1];
461
- if (argc > 2) {
462
- template = argv[2];
463
- }
464
- }
465
- if (filename == Qnil && template == Qnil)
466
- rb_raise(rb_eArgError, "need either template contents or file name.");
467
-
468
- if (template != Qnil)
469
- Check_Type(template, T_STRING);
470
- if (filename != Qnil)
471
- Check_Type(filename, T_STRING);
472
-
473
- fio_str_s str = FIO_STR_INIT;
474
-
475
- mustache_s *m = NULL;
476
- mustache_error_en err;
477
- m = mustache_load(.filename =
478
- (filename == Qnil ? NULL : RSTRING_PTR(filename)),
479
- .filename_len =
480
- (filename == Qnil ? 0 : RSTRING_LEN(filename)),
481
- .data = (template == Qnil ? NULL : RSTRING_PTR(template)),
482
- .data_len = (template == Qnil ? 0 : RSTRING_LEN(template)),
483
- .err = &err);
484
- if (!m)
485
- goto error;
486
- int e = mustache_build(m, .udata1 = &str, .udata2 = (void *)data);
487
- mustache_free(m);
488
- if (e)
489
- goto render_error;
490
- fio_str_info_s i = fio_str_info(&str);
491
- VALUE ret = rb_str_new(i.data, i.len);
492
- fio_str_free(&str);
493
- return ret;
494
-
495
- error:
496
- switch (err) {
497
- case MUSTACHE_OK:
498
- rb_raise(rb_eRuntimeError, "Iodine::Mustache template ok, unknown error.");
499
- break;
500
- case MUSTACHE_ERR_TOO_DEEP:
501
- rb_raise(rb_eRuntimeError, "Iodine::Mustache element nesting too deep.");
502
- break;
503
- case MUSTACHE_ERR_CLOSURE_MISMATCH:
504
- rb_raise(rb_eRuntimeError,
505
- "Iodine::Mustache template error, closure mismatch.");
506
- break;
507
- case MUSTACHE_ERR_FILE_NOT_FOUND:
508
- rb_raise(rb_eLoadError, "Iodine::Mustache template not found.");
509
- break;
510
- case MUSTACHE_ERR_FILE_TOO_BIG:
511
- rb_raise(rb_eLoadError, "Iodine::Mustache template too big.");
512
- break;
513
- case MUSTACHE_ERR_FILE_NAME_TOO_LONG:
514
- rb_raise(rb_eRuntimeError, "Iodine::Mustache template name too long.");
515
- break;
516
- case MUSTACHE_ERR_EMPTY_TEMPLATE:
517
- rb_raise(rb_eRuntimeError, "Iodine::Mustache template is empty.");
518
- break;
519
- case MUSTACHE_ERR_UNKNOWN:
520
- rb_raise(rb_eRuntimeError, "Iodine::Mustache unknown error.");
521
- break;
522
- case MUSTACHE_ERR_USER_ERROR:
523
- rb_raise(rb_eRuntimeError,
524
- "Iodine::Mustache internal error or unexpected data structure.");
525
- break;
526
- case MUSTACHE_ERR_FILE_NAME_TOO_SHORT:
527
- rb_raise(rb_eRuntimeError, "Iodine::Mustache template file name too long.");
528
-
529
- break;
530
- case MUSTACHE_ERR_DELIMITER_TOO_LONG:
531
- rb_raise(rb_eRuntimeError, "Iodine::Mustache new delimiter is too long.");
532
-
533
- break;
534
- case MUSTACHE_ERR_NAME_TOO_LONG:
535
- rb_raise(rb_eRuntimeError,
536
- "Iodine::Mustache section name in template is too long.");
537
-
538
- break;
539
- default:
540
- break;
541
- }
542
- return Qnil;
543
-
544
- render_error:
545
- fio_str_free(&str);
546
- rb_raise(rb_eRuntimeError, "Couldn't build template frome data.");
547
- }
548
-
549
- /* *****************************************************************************
550
- Initialize Iodine::Mustache
551
- ***************************************************************************** */
552
-
553
- void iodine_init_mustache(void) {
554
- call_func_id = rb_intern2("call", 4);
555
- filename_id = rb_id2sym(rb_intern2("filename", 8));
556
- data_id = rb_id2sym(rb_intern2("data", 4));
557
- template_id = rb_id2sym(rb_intern2("template", 8));
558
- rb_global_variable(&filename_id);
559
- rb_global_variable(&data_id);
560
- rb_global_variable(&template_id);
561
- VALUE tmp = rb_define_class_under(IodineModule, "Mustache", rb_cObject);
562
- rb_define_alloc_func(tmp, iodine_mustache_data_alloc_c);
563
- rb_define_method(tmp, "initialize", iodine_mustache_new, -1);
564
- rb_define_method(tmp, "render", iodine_mustache_render, 1);
565
- rb_define_singleton_method(tmp, "render", iodine_mustache_render_klass, -1);
566
- // rb_define_module_function(tmp, "render", iodine_mustache_render_klass, 2);
567
- }