1use super::*;
2
3#[derive(Debug, Clone, PartialEq)]
4pub struct RdList<'a> {
5 path: RdPath,
6 kind: RdListKind,
7 children: &'a [RdNode],
8}
9
10impl<'a> RdList<'a> {
11 pub fn path(&self) -> &RdPath {
12 &self.path
13 }
14 pub fn kind(&self) -> RdListKind {
15 self.kind
16 }
17 pub fn children(&self) -> &'a [RdNode] {
18 self.children
19 }
20
21 pub fn items(&self) -> impl Iterator<Item = Result<RdListItem<'a>, RdShapeError>> + '_ {
22 ListItems {
23 list: self,
24 index: 0,
25 }
26 }
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30#[non_exhaustive]
31pub enum RdListKind {
32 Itemize,
33 Enumerate,
34 Describe,
35}
36
37#[derive(Debug, Clone, PartialEq)]
38#[non_exhaustive]
39pub enum RdListItem<'a> {
40 Delimited(RdDelimitedItem<'a>),
41 Described(RdDescribedItem<'a>),
42}
43
44#[derive(Debug, Clone, PartialEq)]
45pub struct RdDelimitedItem<'a> {
46 path: RdPath,
47 body: &'a [RdNode],
48}
49
50impl<'a> RdDelimitedItem<'a> {
51 pub fn path(&self) -> &RdPath {
52 &self.path
53 }
54 pub fn body(&self) -> &'a [RdNode] {
55 self.body
56 }
57}
58
59#[derive(Debug, Clone, PartialEq)]
60pub struct RdDescribedItem<'a> {
61 path: RdPath,
62 label: &'a [RdNode],
63 body: &'a [RdNode],
64}
65
66impl<'a> RdDescribedItem<'a> {
67 pub fn path(&self) -> &RdPath {
68 &self.path
69 }
70 pub fn label(&self) -> &'a [RdNode] {
71 self.label
72 }
73 pub fn body(&self) -> &'a [RdNode] {
74 self.body
75 }
76}
77impl RdTagged {
78 pub fn inspect_list<'a>(&'a self, base_path: &RdPath) -> Result<RdList<'a>, RdShapeError> {
81 let kind = match self.tag() {
82 RdTag::Itemize => RdListKind::Itemize,
83 RdTag::Enumerate => RdListKind::Enumerate,
84 RdTag::Describe => RdListKind::Describe,
85 tag => {
86 return Err(shape(
87 base_path.clone(),
88 Some(tag.clone()),
89 RdShapeErrorKind::UnexpectedNode {
90 expected: RdExpectedNode::List,
91 actual: RdNodeKind::Tagged,
92 },
93 ));
94 }
95 };
96 if self.option().is_some() {
97 return Err(shape(
98 base_path.clone(),
99 Some(self.tag().clone()),
100 RdShapeErrorKind::UnexpectedOption,
101 ));
102 }
103 Ok(RdList {
104 path: base_path.clone(),
105 kind,
106 children: self.children(),
107 })
108 }
109}
110
111struct ListItems<'list, 'a> {
112 list: &'list RdList<'a>,
113 index: usize,
114}
115
116impl<'list, 'a> Iterator for ListItems<'list, 'a> {
117 type Item = Result<RdListItem<'a>, RdShapeError>;
118
119 fn next(&mut self) -> Option<Self::Item> {
120 if self.list.kind == RdListKind::Describe {
121 while self.index < self.list.children.len() {
122 let index = self.index;
123 self.index += 1;
124 let node = &self.list.children[index];
125 if is_inter_item_trivia(node) {
126 continue;
127 }
128 let path = self.list.path.with_child(index);
129 let Some(tagged) = node.as_tagged() else {
130 return Some(Err(shape(
131 path,
132 node_tag(node),
133 RdShapeErrorKind::UnexpectedContent {
134 actual: RdNodeKind::of(node),
135 },
136 )));
137 };
138 if tagged.tag() != &RdTag::Item {
139 return Some(Err(shape(
140 path,
141 Some(tagged.tag().clone()),
142 RdShapeErrorKind::UnexpectedContent {
143 actual: RdNodeKind::Tagged,
144 },
145 )));
146 }
147 return Some(inspect_two_group_item(tagged, &path).map(|(label, body)| {
148 RdListItem::Described(RdDescribedItem { path, label, body })
149 }));
150 }
151 return None;
152 }
153
154 while self.index < self.list.children.len() {
155 let index = self.index;
156 let node = &self.list.children[index];
157 if is_inter_item_trivia(node) {
158 self.index += 1;
159 continue;
160 }
161 let path = self.list.path.with_child(index);
162 let Some(tagged) = node.as_tagged() else {
163 self.index += 1;
164 return Some(Err(shape(
165 path,
166 node_tag(node),
167 RdShapeErrorKind::UnexpectedContent {
168 actual: RdNodeKind::of(node),
169 },
170 )));
171 };
172 if tagged.tag() != &RdTag::Item {
173 self.index += 1;
174 return Some(Err(shape(
175 path,
176 Some(tagged.tag().clone()),
177 RdShapeErrorKind::UnexpectedContent {
178 actual: RdNodeKind::Tagged,
179 },
180 )));
181 }
182 self.index += 1;
183 let body_start = self.index;
184 while self.index < self.list.children.len() {
185 let candidate = &self.list.children[self.index];
186 if candidate
187 .as_tagged()
188 .is_some_and(|item| item.tag() == &RdTag::Item)
189 {
190 break;
191 }
192 self.index += 1;
193 }
194 let body = &self.list.children[body_start..self.index];
195 if tagged.option().is_some() {
196 return Some(Err(shape(
197 path,
198 Some(RdTag::Item),
199 RdShapeErrorKind::UnexpectedOption,
200 )));
201 }
202 if !tagged.children().is_empty() {
203 return Some(Err(shape(
206 path,
207 Some(RdTag::Item),
208 RdShapeErrorKind::WrongArity {
209 expected: RdArity::Exactly(0),
210 actual: tagged.children().len(),
211 },
212 )));
213 }
214 return Some(Ok(RdListItem::Delimited(RdDelimitedItem { path, body })));
215 }
216 None
217 }
218}
219
220pub(super) fn inspect_two_group_item<'a>(
221 tagged: &'a RdTagged,
222 item_path: &RdPath,
223) -> Result<(&'a [RdNode], &'a [RdNode]), RdShapeError> {
224 if tagged.option().is_some() {
225 return Err(shape(
226 item_path.clone(),
227 Some(RdTag::Item),
228 RdShapeErrorKind::UnexpectedOption,
229 ));
230 }
231 if tagged.children().len() != 2 {
232 return Err(shape(
233 item_path.clone(),
234 Some(RdTag::Item),
235 RdShapeErrorKind::WrongArity {
236 expected: RdArity::Exactly(2),
237 actual: tagged.children().len(),
238 },
239 ));
240 }
241 let [label, body] = tagged.children() else {
242 unreachable!()
243 };
244 for (index, child) in tagged.children().iter().enumerate() {
245 if child.as_group().is_none() {
246 return Err(shape(
247 item_path.with_child(index),
248 Some(RdTag::Item),
249 RdShapeErrorKind::UnexpectedNode {
250 expected: RdExpectedNode::Group,
251 actual: RdNodeKind::of(child),
252 },
253 ));
254 }
255 }
256 Ok((
257 label.as_group().unwrap().children(),
258 body.as_group().unwrap().children(),
259 ))
260}