1pub struct CallbackSpec {
6 pub c_field: &'static str,
8 pub java_method: &'static str,
10 pub doc: &'static str,
12 pub extra: &'static [ExtraParam],
14 pub has_is_header: bool,
16}
17
18pub struct ExtraParam {
19 pub java_name: &'static str,
21 pub java_type: &'static str,
23 pub c_layouts: &'static [&'static str],
26 pub decode: &'static str,
29}
30
31pub const CALLBACKS: &[CallbackSpec] = &[
32 CallbackSpec {
33 c_field: "visit_text",
34 java_method: "visitText",
35 doc: "Called for text nodes.",
36 extra: &[ExtraParam {
37 java_name: "text",
38 java_type: "String",
39 c_layouts: &["ValueLayout.ADDRESS"],
40 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
41 }],
42 has_is_header: false,
43 },
44 CallbackSpec {
45 c_field: "visit_element_start",
46 java_method: "visitElementStart",
47 doc: "Called before entering any element.",
48 extra: &[],
49 has_is_header: false,
50 },
51 CallbackSpec {
52 c_field: "visit_element_end",
53 java_method: "visitElementEnd",
54 doc: "Called after exiting any element; receives the default markdown output.",
55 extra: &[ExtraParam {
56 java_name: "output",
57 java_type: "String",
58 c_layouts: &["ValueLayout.ADDRESS"],
59 decode: "raw_output_0.reinterpret(Long.MAX_VALUE).getString(0)",
60 }],
61 has_is_header: false,
62 },
63 CallbackSpec {
64 c_field: "visit_link",
65 java_method: "visitLink",
66 doc: "Called for anchor links. title is null when the attribute is absent.",
67 extra: &[
68 ExtraParam {
69 java_name: "href",
70 java_type: "String",
71 c_layouts: &["ValueLayout.ADDRESS"],
72 decode: "raw_href_0.reinterpret(Long.MAX_VALUE).getString(0)",
73 },
74 ExtraParam {
75 java_name: "text",
76 java_type: "String",
77 c_layouts: &["ValueLayout.ADDRESS"],
78 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
79 },
80 ExtraParam {
81 java_name: "title",
82 java_type: "String",
83 c_layouts: &["ValueLayout.ADDRESS"],
84 decode: "raw_title_0.equals(MemorySegment.NULL) ? null : raw_title_0.reinterpret(Long.MAX_VALUE).getString(0)",
85 },
86 ],
87 has_is_header: false,
88 },
89 CallbackSpec {
90 c_field: "visit_image",
91 java_method: "visitImage",
92 doc: "Called for images. title is null when absent.",
93 extra: &[
94 ExtraParam {
95 java_name: "src",
96 java_type: "String",
97 c_layouts: &["ValueLayout.ADDRESS"],
98 decode: "raw_src_0.reinterpret(Long.MAX_VALUE).getString(0)",
99 },
100 ExtraParam {
101 java_name: "alt",
102 java_type: "String",
103 c_layouts: &["ValueLayout.ADDRESS"],
104 decode: "raw_alt_0.reinterpret(Long.MAX_VALUE).getString(0)",
105 },
106 ExtraParam {
107 java_name: "title",
108 java_type: "String",
109 c_layouts: &["ValueLayout.ADDRESS"],
110 decode: "raw_title_0.equals(MemorySegment.NULL) ? null : raw_title_0.reinterpret(Long.MAX_VALUE).getString(0)",
111 },
112 ],
113 has_is_header: false,
114 },
115 CallbackSpec {
116 c_field: "visit_heading",
117 java_method: "visitHeading",
118 doc: "Called for heading elements h1-h6. id is null when absent.",
119 extra: &[
120 ExtraParam {
121 java_name: "level",
122 java_type: "int",
123 c_layouts: &["ValueLayout.JAVA_INT"],
124 decode: "(int) raw_level_0",
125 },
126 ExtraParam {
127 java_name: "text",
128 java_type: "String",
129 c_layouts: &["ValueLayout.ADDRESS"],
130 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
131 },
132 ExtraParam {
133 java_name: "id",
134 java_type: "String",
135 c_layouts: &["ValueLayout.ADDRESS"],
136 decode: "raw_id_0.equals(MemorySegment.NULL) ? null : raw_id_0.reinterpret(Long.MAX_VALUE).getString(0)",
137 },
138 ],
139 has_is_header: false,
140 },
141 CallbackSpec {
142 c_field: "visit_code_block",
143 java_method: "visitCodeBlock",
144 doc: "Called for code blocks. lang is null when absent.",
145 extra: &[
146 ExtraParam {
147 java_name: "lang",
148 java_type: "String",
149 c_layouts: &["ValueLayout.ADDRESS"],
150 decode: "raw_lang_0.equals(MemorySegment.NULL) ? null : raw_lang_0.reinterpret(Long.MAX_VALUE).getString(0)",
151 },
152 ExtraParam {
153 java_name: "code",
154 java_type: "String",
155 c_layouts: &["ValueLayout.ADDRESS"],
156 decode: "raw_code_0.reinterpret(Long.MAX_VALUE).getString(0)",
157 },
158 ],
159 has_is_header: false,
160 },
161 CallbackSpec {
162 c_field: "visit_code_inline",
163 java_method: "visitCodeInline",
164 doc: "Called for inline code elements.",
165 extra: &[ExtraParam {
166 java_name: "code",
167 java_type: "String",
168 c_layouts: &["ValueLayout.ADDRESS"],
169 decode: "raw_code_0.reinterpret(Long.MAX_VALUE).getString(0)",
170 }],
171 has_is_header: false,
172 },
173 CallbackSpec {
174 c_field: "visit_list_item",
175 java_method: "visitListItem",
176 doc: "Called for list items.",
177 extra: &[
178 ExtraParam {
179 java_name: "ordered",
180 java_type: "boolean",
181 c_layouts: &["ValueLayout.JAVA_INT"],
182 decode: "((int) raw_ordered_0) != 0",
183 },
184 ExtraParam {
185 java_name: "marker",
186 java_type: "String",
187 c_layouts: &["ValueLayout.ADDRESS"],
188 decode: "raw_marker_0.reinterpret(Long.MAX_VALUE).getString(0)",
189 },
190 ExtraParam {
191 java_name: "text",
192 java_type: "String",
193 c_layouts: &["ValueLayout.ADDRESS"],
194 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
195 },
196 ],
197 has_is_header: false,
198 },
199 CallbackSpec {
200 c_field: "visit_list_start",
201 java_method: "visitListStart",
202 doc: "Called before processing a list.",
203 extra: &[ExtraParam {
204 java_name: "ordered",
205 java_type: "boolean",
206 c_layouts: &["ValueLayout.JAVA_INT"],
207 decode: "((int) raw_ordered_0) != 0",
208 }],
209 has_is_header: false,
210 },
211 CallbackSpec {
212 c_field: "visit_list_end",
213 java_method: "visitListEnd",
214 doc: "Called after processing a list.",
215 extra: &[
216 ExtraParam {
217 java_name: "ordered",
218 java_type: "boolean",
219 c_layouts: &["ValueLayout.JAVA_INT"],
220 decode: "((int) raw_ordered_0) != 0",
221 },
222 ExtraParam {
223 java_name: "output",
224 java_type: "String",
225 c_layouts: &["ValueLayout.ADDRESS"],
226 decode: "raw_output_0.reinterpret(Long.MAX_VALUE).getString(0)",
227 },
228 ],
229 has_is_header: false,
230 },
231 CallbackSpec {
232 c_field: "visit_table_start",
233 java_method: "visitTableStart",
234 doc: "Called before processing a table.",
235 extra: &[],
236 has_is_header: false,
237 },
238 CallbackSpec {
239 c_field: "visit_table_row",
240 java_method: "visitTableRow",
241 doc: "Called for table rows. cells contains the cell text values.",
242 extra: &[ExtraParam {
243 java_name: "cells",
244 java_type: "java.util.List<String>",
245 c_layouts: &["ValueLayout.ADDRESS", "ValueLayout.JAVA_LONG"],
246 decode: "decodeCells(raw_cells_0, (long) raw_cells_1)",
247 }],
248 has_is_header: true,
249 },
250 CallbackSpec {
251 c_field: "visit_table_end",
252 java_method: "visitTableEnd",
253 doc: "Called after processing a table.",
254 extra: &[ExtraParam {
255 java_name: "output",
256 java_type: "String",
257 c_layouts: &["ValueLayout.ADDRESS"],
258 decode: "raw_output_0.reinterpret(Long.MAX_VALUE).getString(0)",
259 }],
260 has_is_header: false,
261 },
262 CallbackSpec {
263 c_field: "visit_blockquote",
264 java_method: "visitBlockquote",
265 doc: "Called for blockquote elements.",
266 extra: &[
267 ExtraParam {
268 java_name: "content",
269 java_type: "String",
270 c_layouts: &["ValueLayout.ADDRESS"],
271 decode: "raw_content_0.reinterpret(Long.MAX_VALUE).getString(0)",
272 },
273 ExtraParam {
274 java_name: "depth",
275 java_type: "long",
276 c_layouts: &["ValueLayout.JAVA_LONG"],
277 decode: "(long) raw_depth_0",
278 },
279 ],
280 has_is_header: false,
281 },
282 CallbackSpec {
283 c_field: "visit_strong",
284 java_method: "visitStrong",
285 doc: "Called for strong/bold elements.",
286 extra: &[ExtraParam {
287 java_name: "text",
288 java_type: "String",
289 c_layouts: &["ValueLayout.ADDRESS"],
290 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
291 }],
292 has_is_header: false,
293 },
294 CallbackSpec {
295 c_field: "visit_emphasis",
296 java_method: "visitEmphasis",
297 doc: "Called for emphasis/italic elements.",
298 extra: &[ExtraParam {
299 java_name: "text",
300 java_type: "String",
301 c_layouts: &["ValueLayout.ADDRESS"],
302 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
303 }],
304 has_is_header: false,
305 },
306 CallbackSpec {
307 c_field: "visit_strikethrough",
308 java_method: "visitStrikethrough",
309 doc: "Called for strikethrough elements.",
310 extra: &[ExtraParam {
311 java_name: "text",
312 java_type: "String",
313 c_layouts: &["ValueLayout.ADDRESS"],
314 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
315 }],
316 has_is_header: false,
317 },
318 CallbackSpec {
319 c_field: "visit_underline",
320 java_method: "visitUnderline",
321 doc: "Called for underline elements.",
322 extra: &[ExtraParam {
323 java_name: "text",
324 java_type: "String",
325 c_layouts: &["ValueLayout.ADDRESS"],
326 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
327 }],
328 has_is_header: false,
329 },
330 CallbackSpec {
331 c_field: "visit_subscript",
332 java_method: "visitSubscript",
333 doc: "Called for subscript elements.",
334 extra: &[ExtraParam {
335 java_name: "text",
336 java_type: "String",
337 c_layouts: &["ValueLayout.ADDRESS"],
338 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
339 }],
340 has_is_header: false,
341 },
342 CallbackSpec {
343 c_field: "visit_superscript",
344 java_method: "visitSuperscript",
345 doc: "Called for superscript elements.",
346 extra: &[ExtraParam {
347 java_name: "text",
348 java_type: "String",
349 c_layouts: &["ValueLayout.ADDRESS"],
350 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
351 }],
352 has_is_header: false,
353 },
354 CallbackSpec {
355 c_field: "visit_mark",
356 java_method: "visitMark",
357 doc: "Called for mark/highlight elements.",
358 extra: &[ExtraParam {
359 java_name: "text",
360 java_type: "String",
361 c_layouts: &["ValueLayout.ADDRESS"],
362 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
363 }],
364 has_is_header: false,
365 },
366 CallbackSpec {
367 c_field: "visit_line_break",
368 java_method: "visitLineBreak",
369 doc: "Called for line break elements.",
370 extra: &[],
371 has_is_header: false,
372 },
373 CallbackSpec {
374 c_field: "visit_horizontal_rule",
375 java_method: "visitHorizontalRule",
376 doc: "Called for horizontal rule elements.",
377 extra: &[],
378 has_is_header: false,
379 },
380 CallbackSpec {
381 c_field: "visit_custom_element",
382 java_method: "visitCustomElement",
383 doc: "Called for custom or unknown elements.",
384 extra: &[
385 ExtraParam {
386 java_name: "tagName",
387 java_type: "String",
388 c_layouts: &["ValueLayout.ADDRESS"],
389 decode: "raw_tagName_0.reinterpret(Long.MAX_VALUE).getString(0)",
390 },
391 ExtraParam {
392 java_name: "html",
393 java_type: "String",
394 c_layouts: &["ValueLayout.ADDRESS"],
395 decode: "raw_html_0.reinterpret(Long.MAX_VALUE).getString(0)",
396 },
397 ],
398 has_is_header: false,
399 },
400 CallbackSpec {
401 c_field: "visit_definition_list_start",
402 java_method: "visitDefinitionListStart",
403 doc: "Called before a definition list.",
404 extra: &[],
405 has_is_header: false,
406 },
407 CallbackSpec {
408 c_field: "visit_definition_term",
409 java_method: "visitDefinitionTerm",
410 doc: "Called for definition term elements.",
411 extra: &[ExtraParam {
412 java_name: "text",
413 java_type: "String",
414 c_layouts: &["ValueLayout.ADDRESS"],
415 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
416 }],
417 has_is_header: false,
418 },
419 CallbackSpec {
420 c_field: "visit_definition_description",
421 java_method: "visitDefinitionDescription",
422 doc: "Called for definition description elements.",
423 extra: &[ExtraParam {
424 java_name: "text",
425 java_type: "String",
426 c_layouts: &["ValueLayout.ADDRESS"],
427 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
428 }],
429 has_is_header: false,
430 },
431 CallbackSpec {
432 c_field: "visit_definition_list_end",
433 java_method: "visitDefinitionListEnd",
434 doc: "Called after a definition list.",
435 extra: &[ExtraParam {
436 java_name: "output",
437 java_type: "String",
438 c_layouts: &["ValueLayout.ADDRESS"],
439 decode: "raw_output_0.reinterpret(Long.MAX_VALUE).getString(0)",
440 }],
441 has_is_header: false,
442 },
443 CallbackSpec {
444 c_field: "visit_form",
445 java_method: "visitForm",
446 doc: "Called for form elements. action and method may be null.",
447 extra: &[
448 ExtraParam {
449 java_name: "action",
450 java_type: "String",
451 c_layouts: &["ValueLayout.ADDRESS"],
452 decode: "raw_action_0.equals(MemorySegment.NULL) ? null : raw_action_0.reinterpret(Long.MAX_VALUE).getString(0)",
453 },
454 ExtraParam {
455 java_name: "method",
456 java_type: "String",
457 c_layouts: &["ValueLayout.ADDRESS"],
458 decode: "raw_method_0.equals(MemorySegment.NULL) ? null : raw_method_0.reinterpret(Long.MAX_VALUE).getString(0)",
459 },
460 ],
461 has_is_header: false,
462 },
463 CallbackSpec {
464 c_field: "visit_input",
465 java_method: "visitInput",
466 doc: "Called for input elements. name and value may be null.",
467 extra: &[
468 ExtraParam {
469 java_name: "inputType",
470 java_type: "String",
471 c_layouts: &["ValueLayout.ADDRESS"],
472 decode: "raw_inputType_0.reinterpret(Long.MAX_VALUE).getString(0)",
473 },
474 ExtraParam {
475 java_name: "name",
476 java_type: "String",
477 c_layouts: &["ValueLayout.ADDRESS"],
478 decode: "raw_name_0.equals(MemorySegment.NULL) ? null : raw_name_0.reinterpret(Long.MAX_VALUE).getString(0)",
479 },
480 ExtraParam {
481 java_name: "value",
482 java_type: "String",
483 c_layouts: &["ValueLayout.ADDRESS"],
484 decode: "raw_value_0.equals(MemorySegment.NULL) ? null : raw_value_0.reinterpret(Long.MAX_VALUE).getString(0)",
485 },
486 ],
487 has_is_header: false,
488 },
489 CallbackSpec {
490 c_field: "visit_button",
491 java_method: "visitButton",
492 doc: "Called for button elements.",
493 extra: &[ExtraParam {
494 java_name: "text",
495 java_type: "String",
496 c_layouts: &["ValueLayout.ADDRESS"],
497 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
498 }],
499 has_is_header: false,
500 },
501 CallbackSpec {
502 c_field: "visit_audio",
503 java_method: "visitAudio",
504 doc: "Called for audio elements. src may be null.",
505 extra: &[ExtraParam {
506 java_name: "src",
507 java_type: "String",
508 c_layouts: &["ValueLayout.ADDRESS"],
509 decode: "raw_src_0.equals(MemorySegment.NULL) ? null : raw_src_0.reinterpret(Long.MAX_VALUE).getString(0)",
510 }],
511 has_is_header: false,
512 },
513 CallbackSpec {
514 c_field: "visit_video",
515 java_method: "visitVideo",
516 doc: "Called for video elements. src may be null.",
517 extra: &[ExtraParam {
518 java_name: "src",
519 java_type: "String",
520 c_layouts: &["ValueLayout.ADDRESS"],
521 decode: "raw_src_0.equals(MemorySegment.NULL) ? null : raw_src_0.reinterpret(Long.MAX_VALUE).getString(0)",
522 }],
523 has_is_header: false,
524 },
525 CallbackSpec {
526 c_field: "visit_iframe",
527 java_method: "visitIframe",
528 doc: "Called for iframe elements. src may be null.",
529 extra: &[ExtraParam {
530 java_name: "src",
531 java_type: "String",
532 c_layouts: &["ValueLayout.ADDRESS"],
533 decode: "raw_src_0.equals(MemorySegment.NULL) ? null : raw_src_0.reinterpret(Long.MAX_VALUE).getString(0)",
534 }],
535 has_is_header: false,
536 },
537 CallbackSpec {
538 c_field: "visit_details",
539 java_method: "visitDetails",
540 doc: "Called for details elements.",
541 extra: &[ExtraParam {
542 java_name: "open",
543 java_type: "boolean",
544 c_layouts: &["ValueLayout.JAVA_INT"],
545 decode: "((int) raw_open_0) != 0",
546 }],
547 has_is_header: false,
548 },
549 CallbackSpec {
550 c_field: "visit_summary",
551 java_method: "visitSummary",
552 doc: "Called for summary elements.",
553 extra: &[ExtraParam {
554 java_name: "text",
555 java_type: "String",
556 c_layouts: &["ValueLayout.ADDRESS"],
557 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
558 }],
559 has_is_header: false,
560 },
561 CallbackSpec {
562 c_field: "visit_figure_start",
563 java_method: "visitFigureStart",
564 doc: "Called before a figure element.",
565 extra: &[],
566 has_is_header: false,
567 },
568 CallbackSpec {
569 c_field: "visit_figcaption",
570 java_method: "visitFigcaption",
571 doc: "Called for figcaption elements.",
572 extra: &[ExtraParam {
573 java_name: "text",
574 java_type: "String",
575 c_layouts: &["ValueLayout.ADDRESS"],
576 decode: "raw_text_0.reinterpret(Long.MAX_VALUE).getString(0)",
577 }],
578 has_is_header: false,
579 },
580 CallbackSpec {
581 c_field: "visit_figure_end",
582 java_method: "visitFigureEnd",
583 doc: "Called after a figure element.",
584 extra: &[ExtraParam {
585 java_name: "output",
586 java_type: "String",
587 c_layouts: &["ValueLayout.ADDRESS"],
588 decode: "raw_output_0.reinterpret(Long.MAX_VALUE).getString(0)",
589 }],
590 has_is_header: false,
591 },
592];
593
594#[cfg(test)]
595mod tests {
596 use super::*;
597
598 #[test]
599 fn callbacks_table_is_non_empty() {
600 assert!(!CALLBACKS.is_empty(), "CALLBACKS must have at least one entry");
601 }
602
603 #[test]
604 fn all_callbacks_have_c_field_and_java_method() {
605 for spec in CALLBACKS {
606 assert!(!spec.c_field.is_empty(), "c_field must not be empty");
607 assert!(!spec.java_method.is_empty(), "java_method must not be empty");
608 }
609 }
610
611 #[test]
612 fn visit_table_row_has_is_header() {
613 let row = CALLBACKS
614 .iter()
615 .find(|s| s.c_field == "visit_table_row")
616 .expect("must have visit_table_row");
617 assert!(row.has_is_header, "visit_table_row must have has_is_header = true");
618 }
619
620 #[test]
621 fn callbacks_with_no_extra_have_empty_extra_slice() {
622 let start = CALLBACKS
623 .iter()
624 .find(|s| s.c_field == "visit_element_start")
625 .expect("must have visit_element_start");
626 assert!(start.extra.is_empty(), "visit_element_start must have no extra params");
627 }
628
629 #[test]
630 fn callbacks_count_matches_expected() {
631 assert_eq!(CALLBACKS.len(), 40, "expected 40 visitor callbacks");
633 }
634}