From 150b6f09277f3318d2c6cc510188ac7fe61d07d4 Mon Sep 17 00:00:00 2001 From: David Aguilar Date: Sat, 23 Mar 2024 22:31:57 -0700 Subject: [PATCH] parser: add an option to keep tags across multiple documents Documents are self-contained and tags defined in the first document are not visible to subsequent documents. Add support for having tags that span across all documents by making the clearing of tags in the parser opt-out. Closes: #10 --- parser/src/parser.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/parser/src/parser.rs b/parser/src/parser.rs index b834c38..1aacfdb 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -115,6 +115,8 @@ pub struct Parser { /// /// Key is the handle, and value is the prefix. tags: HashMap, + /// Make tags global across all documents. + keep_tags: bool, } /// Trait to be implemented in order to use the low-level parsing API. @@ -222,9 +224,17 @@ impl> Parser { // valid anchor_id starts from 1 anchor_id: 1, tags: HashMap::new(), + keep_tags: false, } } + /// Make tags persistent when parsing multiple documents. + #[must_use] + pub fn keep_tags(mut self, value: bool) -> Self { + self.keep_tags = value; + self + } + /// Try to load the next event and return it, but do not consuming it from `self`. /// /// Any subsequent call to [`Parser::peek`] will return the same value, until a call to @@ -595,7 +605,9 @@ impl> Parser { Token(mark, _) => mark, }; - self.tags.clear(); + if !self.keep_tags { + self.tags.clear(); + } if explicit_end { self.state = State::ImplicitDocumentStart; } else { @@ -1050,6 +1062,7 @@ impl> Parser { #[cfg(test)] mod test { use super::{Event, Parser}; + use crate::YamlLoader; #[test] fn test_peek_eq_parse() { @@ -1073,4 +1086,24 @@ a5: *x event.0 != Event::StreamEnd } {} } + + #[test] + fn test_keep_tags_across_multiple_documents() { + let text = r#" +%YAML 1.1 +%TAG !t! tag:test,2024: +--- !t!1 &1 +foo: "bar" +--- !t!2 &2 +baz: "qux" +"#; + let mut loader = YamlLoader::default(); + let mut parser = Parser::new(text.chars()).keep_tags(true); + assert!(parser.load(&mut loader, true).is_ok()); + assert_eq!(loader.documents().len(), 2); + let yaml = &loader.documents()[0]; + assert_eq!(yaml["foo"].as_str(), Some("bar")); + let yaml = &loader.documents()[1]; + assert_eq!(yaml["baz"].as_str(), Some("qux")); + } }