unsafe_libyaml/
dumper.rs

1use crate::api::{yaml_free, yaml_malloc};
2use crate::externs::{memset, strcmp};
3use crate::fmt::WriteToPtr;
4use crate::ops::ForceMul as _;
5use crate::success::{Success, FAIL, OK};
6use crate::yaml::{
7    yaml_anchors_t, yaml_char_t, yaml_document_t, yaml_emitter_t, yaml_event_t, yaml_mark_t,
8    yaml_node_item_t, yaml_node_pair_t, yaml_node_t, YAML_ALIAS_EVENT, YAML_ANY_ENCODING,
9    YAML_DOCUMENT_END_EVENT, YAML_DOCUMENT_START_EVENT, YAML_MAPPING_END_EVENT, YAML_MAPPING_NODE,
10    YAML_MAPPING_START_EVENT, YAML_SCALAR_EVENT, YAML_SCALAR_NODE, YAML_SEQUENCE_END_EVENT,
11    YAML_SEQUENCE_NODE, YAML_SEQUENCE_START_EVENT, YAML_STREAM_END_EVENT, YAML_STREAM_START_EVENT,
12};
13use crate::{libc, yaml_document_delete, yaml_emitter_emit, PointerExt};
14use core::mem::{size_of, MaybeUninit};
15use core::ptr::{self, addr_of_mut};
16
17/// Start a YAML stream.
18///
19/// This function should be used before yaml_emitter_dump() is called.
20pub unsafe fn yaml_emitter_open(emitter: *mut yaml_emitter_t) -> Success {
21    let mut event = MaybeUninit::<yaml_event_t>::uninit();
22    let event = event.as_mut_ptr();
23    let mark = yaml_mark_t {
24        index: 0_u64,
25        line: 0_u64,
26        column: 0_u64,
27    };
28    __assert!(!emitter.is_null());
29    __assert!(!(*emitter).opened);
30    memset(
31        event as *mut libc::c_void,
32        0,
33        size_of::<yaml_event_t>() as libc::c_ulong,
34    );
35    (*event).type_ = YAML_STREAM_START_EVENT;
36    (*event).start_mark = mark;
37    (*event).end_mark = mark;
38    (*event).data.stream_start.encoding = YAML_ANY_ENCODING;
39    if yaml_emitter_emit(emitter, event).fail {
40        return FAIL;
41    }
42    (*emitter).opened = true;
43    OK
44}
45
46/// Finish a YAML stream.
47///
48/// This function should be used after yaml_emitter_dump() is called.
49pub unsafe fn yaml_emitter_close(emitter: *mut yaml_emitter_t) -> Success {
50    let mut event = MaybeUninit::<yaml_event_t>::uninit();
51    let event = event.as_mut_ptr();
52    let mark = yaml_mark_t {
53        index: 0_u64,
54        line: 0_u64,
55        column: 0_u64,
56    };
57    __assert!(!emitter.is_null());
58    __assert!((*emitter).opened);
59    if (*emitter).closed {
60        return OK;
61    }
62    memset(
63        event as *mut libc::c_void,
64        0,
65        size_of::<yaml_event_t>() as libc::c_ulong,
66    );
67    (*event).type_ = YAML_STREAM_END_EVENT;
68    (*event).start_mark = mark;
69    (*event).end_mark = mark;
70    if yaml_emitter_emit(emitter, event).fail {
71        return FAIL;
72    }
73    (*emitter).closed = true;
74    OK
75}
76
77/// Emit a YAML document.
78///
79/// The document object may be generated using the yaml_parser_load() function or
80/// the yaml_document_initialize() function. The emitter takes the
81/// responsibility for the document object and destroys its content after it is
82/// emitted. The document object is destroyed even if the function fails.
83pub unsafe fn yaml_emitter_dump(
84    emitter: *mut yaml_emitter_t,
85    document: *mut yaml_document_t,
86) -> Success {
87    let current_block: u64;
88    let mut event = MaybeUninit::<yaml_event_t>::uninit();
89    let event = event.as_mut_ptr();
90    let mark = yaml_mark_t {
91        index: 0_u64,
92        line: 0_u64,
93        column: 0_u64,
94    };
95    __assert!(!emitter.is_null());
96    __assert!(!document.is_null());
97    let fresh0 = addr_of_mut!((*emitter).document);
98    *fresh0 = document;
99    if !(*emitter).opened {
100        if yaml_emitter_open(emitter).fail {
101            current_block = 5018439318894558507;
102        } else {
103            current_block = 15619007995458559411;
104        }
105    } else {
106        current_block = 15619007995458559411;
107    }
108    match current_block {
109        15619007995458559411 => {
110            if STACK_EMPTY!((*document).nodes) {
111                if yaml_emitter_close(emitter).ok {
112                    yaml_emitter_delete_document_and_anchors(emitter);
113                    return OK;
114                }
115            } else {
116                __assert!((*emitter).opened);
117                let fresh1 = addr_of_mut!((*emitter).anchors);
118                *fresh1 = yaml_malloc(
119                    (size_of::<yaml_anchors_t>() as libc::c_ulong)
120                        .force_mul((*document).nodes.top.c_offset_from((*document).nodes.start)
121                            as libc::c_ulong),
122                ) as *mut yaml_anchors_t;
123                memset(
124                    (*emitter).anchors as *mut libc::c_void,
125                    0,
126                    (size_of::<yaml_anchors_t>() as libc::c_ulong)
127                        .force_mul((*document).nodes.top.c_offset_from((*document).nodes.start)
128                            as libc::c_ulong),
129                );
130                memset(
131                    event as *mut libc::c_void,
132                    0,
133                    size_of::<yaml_event_t>() as libc::c_ulong,
134                );
135                (*event).type_ = YAML_DOCUMENT_START_EVENT;
136                (*event).start_mark = mark;
137                (*event).end_mark = mark;
138                (*event).data.document_start.version_directive = (*document).version_directive;
139                (*event).data.document_start.tag_directives.start =
140                    (*document).tag_directives.start;
141                (*event).data.document_start.tag_directives.end = (*document).tag_directives.end;
142                (*event).data.document_start.implicit = (*document).start_implicit;
143                if yaml_emitter_emit(emitter, event).ok {
144                    yaml_emitter_anchor_node(emitter, 1);
145                    if yaml_emitter_dump_node(emitter, 1).ok {
146                        memset(
147                            event as *mut libc::c_void,
148                            0,
149                            size_of::<yaml_event_t>() as libc::c_ulong,
150                        );
151                        (*event).type_ = YAML_DOCUMENT_END_EVENT;
152                        (*event).start_mark = mark;
153                        (*event).end_mark = mark;
154                        (*event).data.document_end.implicit = (*document).end_implicit;
155                        if yaml_emitter_emit(emitter, event).ok {
156                            yaml_emitter_delete_document_and_anchors(emitter);
157                            return OK;
158                        }
159                    }
160                }
161            }
162        }
163        _ => {}
164    }
165    yaml_emitter_delete_document_and_anchors(emitter);
166    FAIL
167}
168
169unsafe fn yaml_emitter_delete_document_and_anchors(emitter: *mut yaml_emitter_t) {
170    let mut index: libc::c_int;
171    if (*emitter).anchors.is_null() {
172        yaml_document_delete((*emitter).document);
173        let fresh2 = addr_of_mut!((*emitter).document);
174        *fresh2 = ptr::null_mut::<yaml_document_t>();
175        return;
176    }
177    index = 0;
178    while (*(*emitter).document)
179        .nodes
180        .start
181        .wrapping_offset(index as isize)
182        < (*(*emitter).document).nodes.top
183    {
184        let mut node: yaml_node_t = *(*(*emitter).document)
185            .nodes
186            .start
187            .wrapping_offset(index as isize);
188        if !(*(*emitter).anchors.wrapping_offset(index as isize)).serialized {
189            yaml_free(node.tag as *mut libc::c_void);
190            if node.type_ == YAML_SCALAR_NODE {
191                yaml_free(node.data.scalar.value as *mut libc::c_void);
192            }
193        }
194        if node.type_ == YAML_SEQUENCE_NODE {
195            STACK_DEL!(node.data.sequence.items);
196        }
197        if node.type_ == YAML_MAPPING_NODE {
198            STACK_DEL!(node.data.mapping.pairs);
199        }
200        index += 1;
201    }
202    STACK_DEL!((*(*emitter).document).nodes);
203    yaml_free((*emitter).anchors as *mut libc::c_void);
204    let fresh6 = addr_of_mut!((*emitter).anchors);
205    *fresh6 = ptr::null_mut::<yaml_anchors_t>();
206    (*emitter).last_anchor_id = 0;
207    let fresh7 = addr_of_mut!((*emitter).document);
208    *fresh7 = ptr::null_mut::<yaml_document_t>();
209}
210
211unsafe fn yaml_emitter_anchor_node_sub(emitter: *mut yaml_emitter_t, index: libc::c_int) {
212    (*((*emitter).anchors).offset((index - 1) as isize)).references += 1;
213    if (*(*emitter).anchors.offset((index - 1) as isize)).references == 2 {
214        (*emitter).last_anchor_id += 1;
215        (*(*emitter).anchors.offset((index - 1) as isize)).anchor = (*emitter).last_anchor_id;
216    }
217}
218
219unsafe fn yaml_emitter_anchor_node(emitter: *mut yaml_emitter_t, index: libc::c_int) {
220    let node: *mut yaml_node_t = (*(*emitter).document)
221        .nodes
222        .start
223        .wrapping_offset(index as isize)
224        .wrapping_offset(-1_isize);
225    let mut item: *mut yaml_node_item_t;
226    let mut pair: *mut yaml_node_pair_t;
227    let fresh8 =
228        addr_of_mut!((*((*emitter).anchors).wrapping_offset((index - 1) as isize)).references);
229    *fresh8 += 1;
230    if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).references == 1 {
231        match (*node).type_ {
232            YAML_SEQUENCE_NODE => {
233                item = (*node).data.sequence.items.start;
234                while item < (*node).data.sequence.items.top {
235                    yaml_emitter_anchor_node_sub(emitter, *item);
236                    item = item.wrapping_offset(1);
237                }
238            }
239            YAML_MAPPING_NODE => {
240                pair = (*node).data.mapping.pairs.start;
241                while pair < (*node).data.mapping.pairs.top {
242                    yaml_emitter_anchor_node_sub(emitter, (*pair).key);
243                    yaml_emitter_anchor_node_sub(emitter, (*pair).value);
244                    pair = pair.wrapping_offset(1);
245                }
246            }
247            _ => {}
248        }
249    } else if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).references == 2 {
250        let fresh9 = addr_of_mut!((*emitter).last_anchor_id);
251        *fresh9 += 1;
252        (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).anchor = *fresh9;
253    }
254}
255
256unsafe fn yaml_emitter_generate_anchor(
257    _emitter: *mut yaml_emitter_t,
258    anchor_id: libc::c_int,
259) -> *mut yaml_char_t {
260    let anchor: *mut yaml_char_t = yaml_malloc(16_u64) as *mut yaml_char_t;
261    write!(WriteToPtr::new(anchor), "id{:03}\0", anchor_id);
262    anchor
263}
264
265unsafe fn yaml_emitter_dump_node(emitter: *mut yaml_emitter_t, index: libc::c_int) -> Success {
266    let node: *mut yaml_node_t = (*(*emitter).document)
267        .nodes
268        .start
269        .wrapping_offset(index as isize)
270        .wrapping_offset(-1_isize);
271    let anchor_id: libc::c_int = (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).anchor;
272    let mut anchor: *mut yaml_char_t = ptr::null_mut::<yaml_char_t>();
273    if anchor_id != 0 {
274        anchor = yaml_emitter_generate_anchor(emitter, anchor_id);
275    }
276    if (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).serialized {
277        return yaml_emitter_dump_alias(emitter, anchor);
278    }
279    (*(*emitter).anchors.wrapping_offset((index - 1) as isize)).serialized = true;
280    match (*node).type_ {
281        YAML_SCALAR_NODE => yaml_emitter_dump_scalar(emitter, node, anchor),
282        YAML_SEQUENCE_NODE => yaml_emitter_dump_sequence(emitter, node, anchor),
283        YAML_MAPPING_NODE => yaml_emitter_dump_mapping(emitter, node, anchor),
284        _ => __assert!(false),
285    }
286}
287
288unsafe fn yaml_emitter_dump_alias(
289    emitter: *mut yaml_emitter_t,
290    anchor: *mut yaml_char_t,
291) -> Success {
292    let mut event = MaybeUninit::<yaml_event_t>::uninit();
293    let event = event.as_mut_ptr();
294    let mark = yaml_mark_t {
295        index: 0_u64,
296        line: 0_u64,
297        column: 0_u64,
298    };
299    memset(
300        event as *mut libc::c_void,
301        0,
302        size_of::<yaml_event_t>() as libc::c_ulong,
303    );
304    (*event).type_ = YAML_ALIAS_EVENT;
305    (*event).start_mark = mark;
306    (*event).end_mark = mark;
307    (*event).data.alias.anchor = anchor;
308    yaml_emitter_emit(emitter, event)
309}
310
311unsafe fn yaml_emitter_dump_scalar(
312    emitter: *mut yaml_emitter_t,
313    node: *mut yaml_node_t,
314    anchor: *mut yaml_char_t,
315) -> Success {
316    let mut event = MaybeUninit::<yaml_event_t>::uninit();
317    let event = event.as_mut_ptr();
318    let mark = yaml_mark_t {
319        index: 0_u64,
320        line: 0_u64,
321        column: 0_u64,
322    };
323    let plain_implicit = strcmp(
324        (*node).tag as *mut libc::c_char,
325        b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char,
326    ) == 0;
327    let quoted_implicit = strcmp(
328        (*node).tag as *mut libc::c_char,
329        b"tag:yaml.org,2002:str\0" as *const u8 as *const libc::c_char,
330    ) == 0;
331    memset(
332        event as *mut libc::c_void,
333        0,
334        size_of::<yaml_event_t>() as libc::c_ulong,
335    );
336    (*event).type_ = YAML_SCALAR_EVENT;
337    (*event).start_mark = mark;
338    (*event).end_mark = mark;
339    (*event).data.scalar.anchor = anchor;
340    (*event).data.scalar.tag = (*node).tag;
341    (*event).data.scalar.value = (*node).data.scalar.value;
342    (*event).data.scalar.length = (*node).data.scalar.length;
343    (*event).data.scalar.plain_implicit = plain_implicit;
344    (*event).data.scalar.quoted_implicit = quoted_implicit;
345    (*event).data.scalar.style = (*node).data.scalar.style;
346    yaml_emitter_emit(emitter, event)
347}
348
349unsafe fn yaml_emitter_dump_sequence(
350    emitter: *mut yaml_emitter_t,
351    node: *mut yaml_node_t,
352    anchor: *mut yaml_char_t,
353) -> Success {
354    let mut event = MaybeUninit::<yaml_event_t>::uninit();
355    let event = event.as_mut_ptr();
356    let mark = yaml_mark_t {
357        index: 0_u64,
358        line: 0_u64,
359        column: 0_u64,
360    };
361    let implicit = strcmp(
362        (*node).tag as *mut libc::c_char,
363        b"tag:yaml.org,2002:seq\0" as *const u8 as *const libc::c_char,
364    ) == 0;
365    let mut item: *mut yaml_node_item_t;
366    memset(
367        event as *mut libc::c_void,
368        0,
369        size_of::<yaml_event_t>() as libc::c_ulong,
370    );
371    (*event).type_ = YAML_SEQUENCE_START_EVENT;
372    (*event).start_mark = mark;
373    (*event).end_mark = mark;
374    (*event).data.sequence_start.anchor = anchor;
375    (*event).data.sequence_start.tag = (*node).tag;
376    (*event).data.sequence_start.implicit = implicit;
377    (*event).data.sequence_start.style = (*node).data.sequence.style;
378    if yaml_emitter_emit(emitter, event).fail {
379        return FAIL;
380    }
381    item = (*node).data.sequence.items.start;
382    while item < (*node).data.sequence.items.top {
383        if yaml_emitter_dump_node(emitter, *item).fail {
384            return FAIL;
385        }
386        item = item.wrapping_offset(1);
387    }
388    memset(
389        event as *mut libc::c_void,
390        0,
391        size_of::<yaml_event_t>() as libc::c_ulong,
392    );
393    (*event).type_ = YAML_SEQUENCE_END_EVENT;
394    (*event).start_mark = mark;
395    (*event).end_mark = mark;
396    yaml_emitter_emit(emitter, event)
397}
398
399unsafe fn yaml_emitter_dump_mapping(
400    emitter: *mut yaml_emitter_t,
401    node: *mut yaml_node_t,
402    anchor: *mut yaml_char_t,
403) -> Success {
404    let mut event = MaybeUninit::<yaml_event_t>::uninit();
405    let event = event.as_mut_ptr();
406    let mark = yaml_mark_t {
407        index: 0_u64,
408        line: 0_u64,
409        column: 0_u64,
410    };
411    let implicit = strcmp(
412        (*node).tag as *mut libc::c_char,
413        b"tag:yaml.org,2002:map\0" as *const u8 as *const libc::c_char,
414    ) == 0;
415    let mut pair: *mut yaml_node_pair_t;
416    memset(
417        event as *mut libc::c_void,
418        0,
419        size_of::<yaml_event_t>() as libc::c_ulong,
420    );
421    (*event).type_ = YAML_MAPPING_START_EVENT;
422    (*event).start_mark = mark;
423    (*event).end_mark = mark;
424    (*event).data.mapping_start.anchor = anchor;
425    (*event).data.mapping_start.tag = (*node).tag;
426    (*event).data.mapping_start.implicit = implicit;
427    (*event).data.mapping_start.style = (*node).data.mapping.style;
428    if yaml_emitter_emit(emitter, event).fail {
429        return FAIL;
430    }
431    pair = (*node).data.mapping.pairs.start;
432    while pair < (*node).data.mapping.pairs.top {
433        if yaml_emitter_dump_node(emitter, (*pair).key).fail {
434            return FAIL;
435        }
436        if yaml_emitter_dump_node(emitter, (*pair).value).fail {
437            return FAIL;
438        }
439        pair = pair.wrapping_offset(1);
440    }
441    memset(
442        event as *mut libc::c_void,
443        0,
444        size_of::<yaml_event_t>() as libc::c_ulong,
445    );
446    (*event).type_ = YAML_MAPPING_END_EVENT;
447    (*event).start_mark = mark;
448    (*event).end_mark = mark;
449    yaml_emitter_emit(emitter, event)
450}