libyaml_safer/
document.rs

1use std::io::BufRead;
2
3use crate::{
4    AliasData, Anchors, DEFAULT_MAPPING_TAG, DEFAULT_SCALAR_TAG, DEFAULT_SEQUENCE_TAG, Emitter,
5    Error, Event, EventData, MappingStyle, Mark, Parser, ParserInner, Result, ScalarStyle,
6    SequenceStyle, TagDirective, VersionDirective,
7};
8
9/// The document structure.
10#[derive(Clone, Debug)]
11#[non_exhaustive]
12pub struct Document {
13    /// The document nodes.
14    pub nodes: Vec<Node>,
15    /// The version directive.
16    pub version_directive: Option<VersionDirective>,
17    /// The list of tag directives.
18    pub tag_directives: Vec<TagDirective>,
19    /// Is the document start indicator implicit?
20    pub start_implicit: bool,
21    /// Is the document end indicator implicit?
22    pub end_implicit: bool,
23    /// The beginning of the document.
24    pub start_mark: Mark,
25    /// The end of the document.
26    pub end_mark: Mark,
27}
28
29/// The node structure.
30#[derive(Clone, Default, Debug)]
31#[non_exhaustive]
32pub struct Node {
33    /// The node type.
34    pub data: NodeData,
35    /// The node tag.
36    pub tag: Option<String>,
37    /// The beginning of the node.
38    pub start_mark: Mark,
39    /// The end of the node.
40    pub end_mark: Mark,
41}
42
43/// Node types.
44#[derive(Clone, Default, Debug)]
45pub enum NodeData {
46    /// An empty node.
47    #[default]
48    NoNode,
49    /// A scalar node.
50    Scalar {
51        /// The scalar value.
52        value: String,
53        /// The scalar style.
54        style: ScalarStyle,
55    },
56    /// A sequence node.
57    Sequence {
58        /// The stack of sequence items.
59        items: Vec<NodeItem>,
60        /// The sequence style.
61        style: SequenceStyle,
62    },
63    /// A mapping node.
64    Mapping {
65        /// The stack of mapping pairs (key, value).
66        pairs: Vec<NodePair>,
67        /// The mapping style.
68        style: MappingStyle,
69    },
70}
71
72/// An element of a sequence node.
73pub type NodeItem = i32;
74
75/// An element of a mapping node.
76#[derive(Copy, Clone, Default, Debug)]
77#[non_exhaustive]
78pub struct NodePair {
79    /// The key of the element.
80    pub key: i32,
81    /// The value of the element.
82    pub value: i32,
83}
84
85impl Document {
86    /// Create a YAML document.
87    pub fn new(
88        version_directive: Option<VersionDirective>,
89        tag_directives_in: &[TagDirective],
90        start_implicit: bool,
91        end_implicit: bool,
92    ) -> Document {
93        let nodes = Vec::with_capacity(16);
94        let tag_directives = tag_directives_in.to_vec();
95
96        Document {
97            nodes,
98            version_directive,
99            tag_directives,
100            start_implicit,
101            end_implicit,
102            start_mark: Mark::default(),
103            end_mark: Mark::default(),
104        }
105    }
106
107    /// Get a node of a YAML document.
108    ///
109    /// Returns the node object or `None` if `index` is out of range.
110    pub fn get_node_mut(&mut self, index: i32) -> Option<&mut Node> {
111        self.nodes.get_mut(index as usize - 1)
112    }
113
114    /// Get a node of a YAML document.
115    ///
116    /// Returns the node object or `None` if `index` is out of range.
117    pub fn get_node(&self, index: i32) -> Option<&Node> {
118        self.nodes.get(index as usize - 1)
119    }
120
121    /// Get the root of a YAML document node.
122    ///
123    /// The root object is the first object added to the document.
124    ///
125    /// An empty document produced by the parser signifies the end of a YAML stream.
126    ///
127    /// Returns the node object or `None` if the document is empty.
128    pub fn get_root_node(&mut self) -> Option<&mut Node> {
129        self.nodes.get_mut(0)
130    }
131
132    /// Create a SCALAR node and attach it to the document.
133    ///
134    /// The `style` argument may be ignored by the emitter.
135    ///
136    /// Returns the node id or 0 on error.
137    #[must_use]
138    pub fn add_scalar(&mut self, tag: Option<&str>, value: &str, style: ScalarStyle) -> i32 {
139        let mark = Mark {
140            index: 0_u64,
141            line: 0_u64,
142            column: 0_u64,
143        };
144        let tag = tag.unwrap_or(DEFAULT_SCALAR_TAG);
145        let tag_copy = String::from(tag);
146        let value_copy = String::from(value);
147        let node = Node {
148            data: NodeData::Scalar {
149                value: value_copy,
150                style,
151            },
152            tag: Some(tag_copy),
153            start_mark: mark,
154            end_mark: mark,
155        };
156        self.nodes.push(node);
157        self.nodes.len() as i32
158    }
159
160    /// Create a SEQUENCE node and attach it to the document.
161    ///
162    /// The `style` argument may be ignored by the emitter.
163    ///
164    /// Returns the node id, which is a nonzero integer.
165    #[must_use]
166    pub fn add_sequence(&mut self, tag: Option<&str>, style: SequenceStyle) -> i32 {
167        let mark = Mark {
168            index: 0_u64,
169            line: 0_u64,
170            column: 0_u64,
171        };
172
173        let items = Vec::with_capacity(16);
174        let tag = tag.unwrap_or(DEFAULT_SEQUENCE_TAG);
175        let tag_copy = String::from(tag);
176        let node = Node {
177            data: NodeData::Sequence { items, style },
178            tag: Some(tag_copy),
179            start_mark: mark,
180            end_mark: mark,
181        };
182        self.nodes.push(node);
183        self.nodes.len() as i32
184    }
185
186    /// Create a MAPPING node and attach it to the document.
187    ///
188    /// The `style` argument may be ignored by the emitter.
189    ///
190    /// Returns the node id, which is a nonzero integer.
191    #[must_use]
192    pub fn add_mapping(&mut self, tag: Option<&str>, style: MappingStyle) -> i32 {
193        let mark = Mark {
194            index: 0_u64,
195            line: 0_u64,
196            column: 0_u64,
197        };
198        let pairs = Vec::with_capacity(16);
199        let tag = tag.unwrap_or(DEFAULT_MAPPING_TAG);
200        let tag_copy = String::from(tag);
201
202        let node = Node {
203            data: NodeData::Mapping { pairs, style },
204            tag: Some(tag_copy),
205            start_mark: mark,
206            end_mark: mark,
207        };
208
209        self.nodes.push(node);
210        self.nodes.len() as i32
211    }
212
213    /// Add an item to a SEQUENCE node.
214    pub fn append_sequence_item(&mut self, sequence: i32, item: i32) {
215        assert!(sequence > 0 && sequence as usize - 1 < self.nodes.len());
216        assert!(matches!(
217            &self.nodes[sequence as usize - 1].data,
218            NodeData::Sequence { .. }
219        ));
220        assert!(item > 0 && item as usize - 1 < self.nodes.len());
221        if let NodeData::Sequence { items, .. } = &mut self.nodes[sequence as usize - 1].data {
222            items.push(item);
223        }
224    }
225
226    /// Add a pair of a key and a value to a MAPPING node.
227    pub fn yaml_document_append_mapping_pair(&mut self, mapping: i32, key: i32, value: i32) {
228        assert!(mapping > 0 && mapping as usize - 1 < self.nodes.len());
229        assert!(matches!(
230            &self.nodes[mapping as usize - 1].data,
231            NodeData::Mapping { .. }
232        ));
233        assert!(key > 0 && key as usize - 1 < self.nodes.len());
234        assert!(value > 0 && value as usize - 1 < self.nodes.len());
235        let pair = NodePair { key, value };
236        if let NodeData::Mapping { pairs, .. } = &mut self.nodes[mapping as usize - 1].data {
237            pairs.push(pair);
238        }
239    }
240
241    /// Parse the input stream and produce the next YAML document.
242    ///
243    /// Call this function subsequently to produce a sequence of documents
244    /// constituting the input stream.
245    ///
246    /// If the produced document has no root node, it means that the document
247    /// end has been reached.
248    ///
249    /// An application must not alternate the calls of [`Document::load()`] with
250    /// the calls of [`Parser::parse()`]. Doing this will break the parser.
251    pub fn load<R: BufRead>(parser: &mut Parser<R>) -> Result<Document> {
252        let mut document = Document::new(None, &[], false, false);
253        document.nodes.reserve(16);
254
255        if !parser.scanner.stream_start_produced {
256            match parser.parse() {
257                Ok(Event {
258                    data: EventData::StreamStart { .. },
259                    ..
260                }) => (),
261                Ok(_) => panic!("expected stream start"),
262                Err(err) => {
263                    parser.inner.delete_aliases();
264                    return Err(err);
265                }
266            }
267        }
268        if parser.scanner.stream_end_produced {
269            return Ok(document);
270        }
271        let err: Error;
272        match parser.parse() {
273            Ok(event) => {
274                if let EventData::StreamEnd = &event.data {
275                    return Ok(document);
276                }
277                parser.inner.aliases.reserve(16);
278                match document.load_document(parser, event) {
279                    Ok(()) => {
280                        parser.inner.delete_aliases();
281                        return Ok(document);
282                    }
283                    Err(e) => err = e,
284                }
285            }
286            Err(e) => err = e,
287        }
288        parser.inner.delete_aliases();
289        Err(err)
290    }
291
292    fn load_document<R: BufRead>(&mut self, parser: &mut Parser<R>, event: Event) -> Result<()> {
293        let mut ctx = vec![];
294        if let EventData::DocumentStart {
295            version_directive,
296            tag_directives,
297            implicit,
298        } = event.data
299        {
300            self.version_directive = version_directive;
301            self.tag_directives = tag_directives;
302            self.start_implicit = implicit;
303            self.start_mark = event.start_mark;
304            ctx.reserve(16);
305            if let Err(err) = self.load_nodes(parser, &mut ctx) {
306                ctx.clear();
307                return Err(err);
308            }
309            ctx.clear();
310            Ok(())
311        } else {
312            panic!("Expected YAML_DOCUMENT_START_EVENT")
313        }
314    }
315
316    fn load_nodes<R: BufRead>(&mut self, parser: &mut Parser<R>, ctx: &mut Vec<i32>) -> Result<()> {
317        let end_implicit;
318        let end_mark;
319
320        loop {
321            let event = parser.parse()?;
322            match event.data {
323                EventData::StreamStart { .. } => panic!("unexpected stream start event"),
324                EventData::StreamEnd => panic!("unexpected stream end event"),
325                EventData::DocumentStart { .. } => panic!("unexpected document start event"),
326                EventData::DocumentEnd { implicit } => {
327                    end_implicit = implicit;
328                    end_mark = event.end_mark;
329                    break;
330                }
331                EventData::Alias { .. } => {
332                    self.load_alias(&parser.inner, event, ctx)?;
333                }
334                EventData::Scalar { .. } => {
335                    self.load_scalar(&mut parser.inner, event, ctx)?;
336                }
337                EventData::SequenceStart { .. } => {
338                    self.load_sequence(&mut parser.inner, event, ctx)?;
339                }
340                EventData::SequenceEnd => {
341                    self.load_sequence_end(event, ctx)?;
342                }
343                EventData::MappingStart { .. } => {
344                    self.load_mapping(&mut parser.inner, event, ctx)?;
345                }
346                EventData::MappingEnd => {
347                    self.load_mapping_end(event, ctx)?;
348                }
349            }
350        }
351        self.end_implicit = end_implicit;
352        self.end_mark = end_mark;
353        Ok(())
354    }
355
356    fn register_anchor(
357        &mut self,
358        parser: &mut ParserInner,
359        index: i32,
360        anchor: Option<String>,
361    ) -> Result<()> {
362        let anchor = match anchor {
363            Some(anchor) => anchor,
364            None => return Ok(()),
365        };
366        let data = AliasData {
367            anchor,
368            index,
369            mark: self.nodes[index as usize - 1].start_mark,
370        };
371        for alias_data in &parser.aliases {
372            if alias_data.anchor == data.anchor {
373                return Err(Error::composer(
374                    "found duplicate anchor; first occurrence",
375                    alias_data.mark,
376                    "second occurrence",
377                    data.mark,
378                ));
379            }
380        }
381        parser.aliases.push(data);
382        Ok(())
383    }
384
385    fn load_node_add(&mut self, ctx: &[i32], index: i32) -> Result<()> {
386        let parent_index = match ctx.last() {
387            Some(parent_index) => parent_index,
388            None => return Ok(()),
389        };
390        let parent_index = *parent_index;
391        let parent = &mut self.nodes[parent_index as usize - 1];
392        match parent.data {
393            NodeData::Sequence { ref mut items, .. } => {
394                items.push(index);
395            }
396            NodeData::Mapping { ref mut pairs, .. } => match pairs.last_mut() {
397                // If the last pair does not have a value, set `index` as the value.
398                Some(pair @ NodePair { value: 0, .. }) => {
399                    pair.value = index;
400                }
401                // Otherwise push a new pair where `index` is the key.
402                _ => pairs.push(NodePair {
403                    key: index,
404                    value: 0,
405                }),
406            },
407            _ => {
408                panic!("document parent node is not a sequence or a mapping")
409            }
410        }
411        Ok(())
412    }
413
414    fn load_alias(&mut self, parser: &ParserInner, event: Event, ctx: &[i32]) -> Result<()> {
415        let anchor = match &event.data {
416            EventData::Alias { anchor } => anchor,
417            _ => unreachable!(),
418        };
419
420        for alias_data in &parser.aliases {
421            if alias_data.anchor == *anchor {
422                return self.load_node_add(ctx, alias_data.index);
423            }
424        }
425
426        Err(Error::composer(
427            "",
428            Mark::default(),
429            "found undefined alias",
430            event.start_mark,
431        ))
432    }
433
434    fn load_scalar(&mut self, parser: &mut ParserInner, event: Event, ctx: &[i32]) -> Result<()> {
435        let (mut tag, value, style, anchor) = match event.data {
436            EventData::Scalar {
437                tag,
438                value,
439                style,
440                anchor,
441                ..
442            } => (tag, value, style, anchor),
443            _ => unreachable!(),
444        };
445
446        if tag.is_none() || tag.as_deref() == Some("!") {
447            tag = Some(String::from(DEFAULT_SCALAR_TAG));
448        }
449        let node = Node {
450            data: NodeData::Scalar { value, style },
451            tag,
452            start_mark: event.start_mark,
453            end_mark: event.end_mark,
454        };
455        self.nodes.push(node);
456        let index: i32 = self.nodes.len() as i32;
457        self.register_anchor(parser, index, anchor)?;
458        self.load_node_add(ctx, index)
459    }
460
461    fn load_sequence(
462        &mut self,
463        parser: &mut ParserInner,
464        event: Event,
465        ctx: &mut Vec<i32>,
466    ) -> Result<()> {
467        let (anchor, mut tag, style) = match event.data {
468            EventData::SequenceStart {
469                anchor,
470                tag,
471                style,
472                ..
473            } => (anchor, tag, style),
474            _ => unreachable!(),
475        };
476
477        let mut items = Vec::with_capacity(16);
478
479        if tag.is_none() || tag.as_deref() == Some("!") {
480            tag = Some(String::from(DEFAULT_SEQUENCE_TAG));
481        }
482
483        let node = Node {
484            data: NodeData::Sequence {
485                items: core::mem::take(&mut items),
486                style,
487            },
488            tag,
489            start_mark: event.start_mark,
490            end_mark: event.end_mark,
491        };
492
493        self.nodes.push(node);
494        let index: i32 = self.nodes.len() as i32;
495        self.register_anchor(parser, index, anchor)?;
496        self.load_node_add(ctx, index)?;
497        ctx.push(index);
498        Ok(())
499    }
500
501    fn load_sequence_end(&mut self, event: Event, ctx: &mut Vec<i32>) -> Result<()> {
502        let index = match ctx.last().copied() {
503            Some(index) => index,
504            None => panic!("sequence_end without a current sequence"),
505        };
506        assert!(matches!(
507            self.nodes[index as usize - 1].data,
508            NodeData::Sequence { .. }
509        ));
510        self.nodes[index as usize - 1].end_mark = event.end_mark;
511        ctx.pop();
512        Ok(())
513    }
514
515    fn load_mapping(
516        &mut self,
517        parser: &mut ParserInner,
518        event: Event,
519        ctx: &mut Vec<i32>,
520    ) -> Result<()> {
521        let (anchor, mut tag, style) = match event.data {
522            EventData::MappingStart {
523                anchor,
524                tag,
525                style,
526                ..
527            } => (anchor, tag, style),
528            _ => unreachable!(),
529        };
530
531        let mut pairs = Vec::with_capacity(16);
532
533        if tag.is_none() || tag.as_deref() == Some("!") {
534            tag = Some(String::from(DEFAULT_MAPPING_TAG));
535        }
536        let node = Node {
537            data: NodeData::Mapping {
538                pairs: core::mem::take(&mut pairs),
539                style,
540            },
541            tag,
542            start_mark: event.start_mark,
543            end_mark: event.end_mark,
544        };
545        self.nodes.push(node);
546        let index: i32 = self.nodes.len() as i32;
547        self.register_anchor(parser, index, anchor)?;
548        self.load_node_add(ctx, index)?;
549        ctx.push(index);
550        Ok(())
551    }
552
553    fn load_mapping_end(&mut self, event: Event, ctx: &mut Vec<i32>) -> Result<()> {
554        let index = match ctx.last().copied() {
555            Some(index) => index,
556            None => panic!("mapping_end without a current mapping"),
557        };
558        assert!(matches!(
559            self.nodes[index as usize - 1].data,
560            NodeData::Mapping { .. }
561        ));
562        self.nodes[index as usize - 1].end_mark = event.end_mark;
563        ctx.pop();
564        Ok(())
565    }
566
567    /// Emit a YAML document.
568    ///
569    /// The document object may be generated using the [`Document::load()`]
570    /// function or the [`Document::new()`] function.
571    pub fn dump(mut self, emitter: &mut Emitter) -> Result<()> {
572        if !emitter.opened {
573            if let Err(err) = emitter.open() {
574                emitter.reset_anchors();
575                return Err(err);
576            }
577        }
578        if self.nodes.is_empty() {
579            // TODO: Do we really want to close the emitter just because the
580            // document contains no nodes? Isn't it OK to emit multiple documents in
581            // the same stream?
582            emitter.close()?;
583        } else {
584            assert!(emitter.opened);
585            emitter.anchors = vec![Anchors::default(); self.nodes.len()];
586            let event = Event::new(EventData::DocumentStart {
587                version_directive: self.version_directive,
588                tag_directives: core::mem::take(&mut self.tag_directives),
589                implicit: self.start_implicit,
590            });
591            emitter.emit(event)?;
592            self.anchor_node(emitter, 1);
593            self.dump_node(emitter, 1)?;
594            let event = Event::document_end(self.end_implicit);
595            emitter.emit(event)?;
596        }
597
598        emitter.reset_anchors();
599        Ok(())
600    }
601
602    fn anchor_node(&self, emitter: &mut Emitter, index: i32) {
603        let node = &self.nodes[index as usize - 1];
604        emitter.anchors[index as usize - 1].references += 1;
605        if emitter.anchors[index as usize - 1].references == 1 {
606            match &node.data {
607                NodeData::Sequence { items, .. } => {
608                    for item in items {
609                        emitter.anchor_node_sub(*item);
610                    }
611                }
612                NodeData::Mapping { pairs, .. } => {
613                    for pair in pairs {
614                        emitter.anchor_node_sub(pair.key);
615                        emitter.anchor_node_sub(pair.value);
616                    }
617                }
618                _ => {}
619            }
620        } else if emitter.anchors[index as usize - 1].references == 2 {
621            emitter.last_anchor_id += 1;
622            emitter.anchors[index as usize - 1].anchor = emitter.last_anchor_id;
623        }
624    }
625
626    fn dump_node(&mut self, emitter: &mut Emitter, index: i32) -> Result<()> {
627        assert!(index > 0);
628        let node = &mut self.nodes[index as usize - 1];
629        let anchor_id: i32 = emitter.anchors[index as usize - 1].anchor;
630        let mut anchor: Option<String> = None;
631        if anchor_id != 0 {
632            anchor = Some(Emitter::generate_anchor(anchor_id));
633        }
634        if emitter.anchors[index as usize - 1].serialized {
635            return Self::dump_alias(emitter, anchor.unwrap());
636        }
637        emitter.anchors[index as usize - 1].serialized = true;
638
639        let node = core::mem::take(node);
640        match node.data {
641            NodeData::Scalar { .. } => Self::dump_scalar(emitter, node, anchor),
642            NodeData::Sequence { .. } => self.dump_sequence(emitter, node, anchor),
643            NodeData::Mapping { .. } => self.dump_mapping(emitter, node, anchor),
644            _ => unreachable!("document node is neither a scalar, sequence, or a mapping"),
645        }
646    }
647
648    fn dump_alias(emitter: &mut Emitter, anchor: String) -> Result<()> {
649        let event = Event::new(EventData::Alias { anchor });
650        emitter.emit(event)
651    }
652
653    fn dump_scalar(emitter: &mut Emitter, node: Node, anchor: Option<String>) -> Result<()> {
654        let plain_implicit = node.tag.as_deref() == Some(DEFAULT_SCALAR_TAG);
655        let quoted_implicit = node.tag.as_deref() == Some(DEFAULT_SCALAR_TAG); // TODO: Why compare twice?! (even the C code does this)
656
657        let (value, style) = match node.data {
658            NodeData::Scalar { value, style } => (value, style),
659            _ => unreachable!(),
660        };
661        let event = Event::new(EventData::Scalar {
662            anchor,
663            tag: node.tag,
664            value,
665            plain_implicit,
666            quoted_implicit,
667            style,
668        });
669        emitter.emit(event)
670    }
671
672    fn dump_sequence(
673        &mut self,
674        emitter: &mut Emitter,
675        node: Node,
676        anchor: Option<String>,
677    ) -> Result<()> {
678        let implicit = node.tag.as_deref() == Some(DEFAULT_SEQUENCE_TAG);
679
680        let (items, style) = match node.data {
681            NodeData::Sequence { items, style } => (items, style),
682            _ => unreachable!(),
683        };
684        let event = Event::new(EventData::SequenceStart {
685            anchor,
686            tag: node.tag,
687            implicit,
688            style,
689        });
690
691        emitter.emit(event)?;
692        for item in items {
693            self.dump_node(emitter, item)?;
694        }
695        let event = Event::sequence_end();
696        emitter.emit(event)
697    }
698
699    fn dump_mapping(
700        &mut self,
701        emitter: &mut Emitter,
702        node: Node,
703        anchor: Option<String>,
704    ) -> Result<()> {
705        let implicit = node.tag.as_deref() == Some(DEFAULT_MAPPING_TAG);
706
707        let (pairs, style) = match node.data {
708            NodeData::Mapping { pairs, style } => (pairs, style),
709            _ => unreachable!(),
710        };
711        let event = Event::new(EventData::MappingStart {
712            anchor,
713            tag: node.tag,
714            implicit,
715            style,
716        });
717
718        emitter.emit(event)?;
719        for pair in pairs {
720            self.dump_node(emitter, pair.key)?;
721            self.dump_node(emitter, pair.value)?;
722        }
723        let event = Event::mapping_end();
724        emitter.emit(event)
725    }
726}