1pub mod attribute;
22
23mod align;
24mod anchor;
25mod bibliography;
26mod clear_float;
27mod clone;
28mod code;
29mod container;
30mod date;
31mod definition_list;
32mod element;
33mod embed;
34mod heading;
35mod image;
36mod link;
37mod list;
38mod module;
39mod partial;
40mod ruby;
41mod tab;
42mod table;
43mod tag;
44mod variables;
45
46pub use self::align::*;
47pub use self::anchor::*;
48pub use self::attribute::AttributeMap;
49pub use self::bibliography::*;
50pub use self::clear_float::*;
51pub use self::code::CodeBlock;
52pub use self::container::*;
53pub use self::date::DateItem;
54pub use self::definition_list::*;
55pub use self::element::*;
56pub use self::embed::*;
57pub use self::heading::*;
58pub use self::image::*;
59pub use self::link::*;
60pub use self::list::*;
61pub use self::module::*;
62pub use self::partial::*;
63pub use self::ruby::*;
64pub use self::tab::*;
65pub use self::table::*;
66pub use self::tag::*;
67pub use self::variables::*;
68
69use self::clone::{elements_lists_to_owned, elements_to_owned, string_to_owned};
70use crate::parsing::{ParseError, ParseOutcome};
71use std::borrow::Cow;
72use std::ops::Not;
73
74#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq)]
75#[serde(rename_all = "kebab-case")]
76pub struct SyntaxTree<'t> {
77 pub elements: Vec<Element<'t>>,
83
84 #[serde(default, skip_serializing_if = "Vec::is_empty")]
89 pub table_of_contents: Vec<Element<'t>>,
90
91 #[serde(default, skip_serializing_if = "Vec::is_empty")]
93 pub html_blocks: Vec<Cow<'t, str>>,
94
95 #[serde(default, skip_serializing_if = "Vec::is_empty")]
97 pub code_blocks: Vec<CodeBlock<'t>>,
98
99 #[serde(default, skip_serializing_if = "Vec::is_empty")]
101 pub footnotes: Vec<Vec<Element<'t>>>,
102
103 #[serde(default, skip_serializing_if = "Not::not")]
110 pub needs_footnote_block: bool,
111
112 #[serde(default, skip_serializing_if = "BibliographyList::is_empty")]
114 pub bibliographies: BibliographyList<'t>,
115
116 #[serde(skip)]
120 pub wikitext_len: usize,
121}
122
123impl<'t> SyntaxTree<'t> {
124 pub(crate) fn from_element_result(
125 elements: Vec<Element<'t>>,
126 errors: Vec<ParseError>,
127 (html_blocks, code_blocks): (Vec<Cow<'t, str>>, Vec<CodeBlock<'t>>),
128 table_of_contents: Vec<Element<'t>>,
129 (footnotes, needs_footnote_block): (Vec<Vec<Element<'t>>>, bool),
130 bibliographies: BibliographyList<'t>,
131 wikitext_len: usize,
132 ) -> ParseOutcome<Self> {
133 let tree = SyntaxTree {
134 elements,
135 table_of_contents,
136 html_blocks,
137 code_blocks,
138 footnotes,
139 needs_footnote_block,
140 bibliographies,
141 wikitext_len,
142 };
143 ParseOutcome::new(tree, errors)
144 }
145
146 pub fn to_owned(&self) -> SyntaxTree<'static> {
147 SyntaxTree {
148 elements: elements_to_owned(&self.elements),
149 table_of_contents: elements_to_owned(&self.table_of_contents),
150 html_blocks: self
151 .html_blocks
152 .iter()
153 .map(|html| string_to_owned(html))
154 .collect(),
155 code_blocks: self
156 .code_blocks
157 .iter()
158 .map(|code| code.to_owned())
159 .collect(),
160 footnotes: elements_lists_to_owned(&self.footnotes),
161 needs_footnote_block: self.needs_footnote_block,
162 bibliographies: self.bibliographies.to_owned(),
163 wikitext_len: self.wikitext_len,
164 }
165 }
166}
167
168#[test]
169fn borrowed_to_owned() {
170 use std::mem;
171
172 let tree_1: SyntaxTree<'_> = SyntaxTree::default();
173 let tree_2: SyntaxTree<'static> = tree_1.to_owned();
174
175 mem::drop(tree_1);
176
177 let tree_3: SyntaxTree<'static> = tree_2.clone();
178
179 mem::drop(tree_3);
180}