asciidoc_parser/document/
document.rs1use std::{marker::PhantomData, slice::Iter};
4
5use self_cell::self_cell;
6
7use crate::{
8 Parser, Span,
9 attributes::Attrlist,
10 blocks::{Block, ContentModel, IsBlock, parse_utils::parse_blocks_until},
11 document::Header,
12 strings::CowStr,
13 warnings::Warning,
14};
15
16#[derive(Eq, PartialEq)]
29pub struct Document<'src> {
30 internal: Internal,
31 _phantom: PhantomData<&'src ()>,
32}
33
34#[derive(Debug, Eq, PartialEq)]
37struct InternalDependent<'src> {
38 header: Header<'src>,
39 blocks: Vec<Block<'src>>,
40 source: Span<'src>,
41 warnings: Vec<Warning<'src>>,
42}
43
44self_cell! {
45 struct Internal {
47 owner: String,
48 #[covariant]
49 dependent: InternalDependent,
50 }
51 impl {Debug, Eq, PartialEq}
52}
53
54impl<'src> Document<'src> {
55 pub(crate) fn parse(source: &str, parser: &mut Parser) -> Self {
56 let owned_source = source.to_string();
57
58 let internal = Internal::new(owned_source, |owned_src| {
59 let source = Span::new(owned_src);
60
61 let mi = Header::parse(source, parser);
62 let next = mi.item.after;
63
64 let header = mi.item.item;
65 let mut warnings = mi.warnings;
66
67 let mut maw_blocks = parse_blocks_until(next, |_| false, parser);
68
69 if !maw_blocks.warnings.is_empty() {
70 warnings.append(&mut maw_blocks.warnings);
71 }
72
73 InternalDependent {
74 header,
75 blocks: maw_blocks.item.item,
76 source: source.trim_trailing_whitespace(),
77 warnings,
78 }
79 });
80
81 Self {
82 internal,
83 _phantom: PhantomData,
84 }
85 }
86
87 pub fn header(&self) -> &Header<'_> {
89 &self.internal.borrow_dependent().header
90 }
91
92 pub fn warnings(&self) -> Iter<'_, Warning<'_>> {
94 self.internal.borrow_dependent().warnings.iter()
95 }
96
97 pub fn span(&self) -> Span<'_> {
99 self.internal.borrow_dependent().source
100 }
101}
102
103impl<'src> IsBlock<'src> for Document<'src> {
104 fn content_model(&self) -> ContentModel {
105 ContentModel::Compound
106 }
107
108 fn raw_context(&self) -> CowStr<'src> {
109 "document".into()
110 }
111
112 fn nested_blocks(&'src self) -> Iter<'src, Block<'src>> {
113 self.internal.borrow_dependent().blocks.iter()
114 }
115
116 fn title_source(&'src self) -> Option<Span<'src>> {
117 None
119 }
120
121 fn title(&self) -> Option<&str> {
122 None
124 }
125
126 fn anchor(&'src self) -> Option<Span<'src>> {
127 None
128 }
129
130 fn attrlist(&'src self) -> Option<&'src Attrlist<'src>> {
131 None
133 }
134}
135
136impl std::fmt::Debug for Document<'_> {
137 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138 let dependent = self.internal.borrow_dependent();
139 f.debug_struct("Document")
140 .field("header", &dependent.header)
141 .field("blocks", &dependent.blocks)
142 .field("source", &dependent.source)
143 .field("warnings", &dependent.warnings)
144 .finish()
145 }
146}