1use crate::doc_ref::{DocRef, ParentRef};
2use fieldwork::Fieldwork;
3use rustdoc_types::{Id, Item, ItemEnum, Type, Use};
4use std::collections::hash_map::Values;
5
6pub struct MethodIter<'a> {
7 item: DocRef<'a, Item>,
8 impl_block_iter: InherentImplBlockIter<'a>,
9 current_item_iter: Option<std::slice::Iter<'a, Id>>,
10}
11
12impl<'a> MethodIter<'a> {
13 pub(crate) fn new(item: DocRef<'a, Item>) -> Self {
14 let impl_block_iter = InherentImplBlockIter::new(item);
15 Self {
16 item,
17 impl_block_iter,
18 current_item_iter: None,
19 }
20 }
21}
22
23impl<'a> DocRef<'a, Item> {
24 pub fn methods(&self) -> MethodIter<'a> {
25 MethodIter::new(*self)
26 }
27
28 pub fn traits(&self) -> TraitIter<'a> {
29 TraitIter::new(*self)
30 }
31
32 pub fn child_items(&self) -> ChildItems<'a> {
33 ChildItems::new(*self)
34 }
35}
36
37impl<'a, T> DocRef<'a, T> {
38 pub fn id_iter(&self, ids: &'a [Id]) -> IdIter<'a, T> {
39 IdIter::new(*self, ids)
40 }
41}
42
43pub struct TraitIter<'a> {
44 item: DocRef<'a, Item>,
45 item_iter: Values<'a, Id, Item>,
46}
47impl<'a> TraitIter<'a> {
48 fn new(item: DocRef<'a, Item>) -> Self {
49 let item_iter = item.crate_docs().index.values();
50 Self { item, item_iter }
51 }
52}
53
54impl<'a> Iterator for TraitIter<'a> {
55 type Item = DocRef<'a, Item>;
56
57 fn next(&mut self) -> Option<Self::Item> {
58 for item in &mut self.item_iter {
59 if let ItemEnum::Impl(impl_block) = &item.inner
60 && let Type::ResolvedPath(path) = &impl_block.for_
61 && path.id == self.item.id
62 && impl_block.trait_.is_some()
63 {
64 return Some(self.item.build_ref(item));
65 }
66 }
67 None
68 }
69}
70
71pub struct ImplementorIter<'a> {
72 trait_item: DocRef<'a, Item>,
73 item_iter: Values<'a, Id, Item>,
74}
75
76impl<'a> ImplementorIter<'a> {
77 fn new(trait_item: DocRef<'a, Item>) -> Self {
78 let item_iter = trait_item.crate_docs().index.values();
79 Self {
80 trait_item,
81 item_iter,
82 }
83 }
84}
85
86impl<'a> DocRef<'a, Item> {
87 pub fn implementors(&self) -> ImplementorIter<'a> {
89 ImplementorIter::new(*self)
90 }
91}
92
93impl<'a> Iterator for ImplementorIter<'a> {
94 type Item = DocRef<'a, Item>;
95
96 fn next(&mut self) -> Option<Self::Item> {
97 for item in &mut self.item_iter {
98 if let ItemEnum::Impl(impl_block) = &item.inner
99 && let Some(trait_path) = &impl_block.trait_
100 && trait_path.id == self.trait_item.id
101 && !impl_block.is_negative
102 {
103 return Some(self.trait_item.build_ref(item));
104 }
105 }
106 None
107 }
108}
109
110impl<'a> Iterator for MethodIter<'a> {
111 type Item = DocRef<'a, Item>;
112
113 fn next(&mut self) -> Option<Self::Item> {
114 loop {
115 if let Some(current_item_iter) = &mut self.current_item_iter {
116 for id in current_item_iter {
117 if let Some(item) = self.item.get(id) {
118 return Some(item.with_parent(self.item));
119 }
120 }
121 }
122
123 if let Some(item) = self.impl_block_iter.next()
124 && let ItemEnum::Impl(impl_block) = &item.item().inner
125 {
126 self.current_item_iter = Some(impl_block.items.iter())
127 } else {
128 return None;
129 }
130 }
131 }
132}
133
134#[derive(Debug, Fieldwork)]
135pub struct IdIter<'a, T> {
136 item: DocRef<'a, T>,
137 id_iter: std::slice::Iter<'a, Id>,
138 glob_iter: Option<Box<IdIter<'a, Item>>>,
139 #[field(with)]
140 include_use: bool,
141 #[field(with(vis = "pub(crate)", option_set_some, into))]
142 parent: Option<ParentRef<'a>>,
143}
144
145impl<'a, T> IdIter<'a, T> {
146 pub(crate) fn new(item: DocRef<'a, T>, ids: &'a [Id]) -> Self {
147 Self {
148 item,
149 id_iter: ids.iter(),
150 glob_iter: None,
151 include_use: false,
152 parent: None,
153 }
154 }
155}
156
157impl<'a, T> Iterator for IdIter<'a, T> {
158 type Item = DocRef<'a, Item>;
159
160 fn next(&mut self) -> Option<Self::Item> {
161 loop {
162 if let Some(glob_iter) = self.glob_iter.as_mut() {
163 if let Some(item) = glob_iter.next() {
164 return Some(item);
165 } else {
166 self.glob_iter = None;
167 }
168 }
169
170 for id in &mut self.id_iter {
171 if let Some(item) = self.item.get(id) {
172 if let ItemEnum::Use(use_item) = item.inner() {
173 if self.include_use {
174 return Some(item);
175 }
176
177 let source_item = use_item
178 .id
179 .and_then(|id| item.crate_docs().get(item.navigator(), &id))
180 .or_else(|| {
181 item.navigator().resolve_path(&use_item.source, &mut vec![])
182 })?;
183
184 if use_item.is_glob {
185 self.glob_iter = match source_item.inner() {
186 ItemEnum::Module(module) => {
187 Some(Box::new(source_item.id_iter(&module.items)))
188 }
189 ItemEnum::Enum(enum_item) => {
190 Some(Box::new(source_item.id_iter(&enum_item.variants)))
191 }
192 _ => None,
193 };
194
195 break;
196 } else {
197 return Some(source_item.with_name(&use_item.name));
198 }
199 }
200 return Some(match self.parent {
201 Some(parent) => item.with_parent(parent),
202 None => item,
203 });
204 }
205 }
206 if self.glob_iter.is_none() {
207 break;
208 }
209 }
210
211 None
212 }
213}
214
215pub(crate) struct InherentImplBlockIter<'a> {
216 item: DocRef<'a, Item>,
217 item_iter: Values<'a, Id, Item>,
218}
219
220impl<'a> InherentImplBlockIter<'a> {
221 pub(crate) fn new(item: DocRef<'a, Item>) -> Self {
222 let item_iter = item.crate_docs().index.values();
223 Self { item, item_iter }
224 }
225}
226
227impl<'a> Iterator for InherentImplBlockIter<'a> {
228 type Item = DocRef<'a, Item>;
229
230 fn next(&mut self) -> Option<Self::Item> {
231 for item in &mut self.item_iter {
232 if let ItemEnum::Impl(impl_block) = &item.inner
233 && let Type::ResolvedPath(path) = &impl_block.for_
234 && path.id == self.item.id
235 && impl_block.trait_.is_none()
236 {
237 return Some(DocRef::new(self.item.navigator(), self.item, item));
238 }
239 }
240 None
241 }
242}
243
244pub enum ChildItems<'a> {
245 AssociatedMethods(MethodIter<'a>),
246 Module(IdIter<'a, Item>),
247 Use(Option<DocRef<'a, Use>>, Option<IdIter<'a, Item>>, bool),
248 Enum(IdIter<'a, Item>, MethodIter<'a>),
249 None,
250}
251
252impl<'a> Iterator for ChildItems<'a> {
253 type Item = DocRef<'a, Item>;
254
255 fn next(&mut self) -> Option<Self::Item> {
256 loop {
257 match self {
258 ChildItems::AssociatedMethods(method_iter) => return method_iter.next(),
259 ChildItems::Module(id_iter) => return id_iter.next(),
260 ChildItems::Enum(id_iter, method_iter) => {
261 return id_iter.next().or_else(|| method_iter.next());
262 }
263 ChildItems::Use(_, Some(id_iter), _) => return id_iter.next(),
264 ChildItems::Use(use_item_option @ Some(_), id_iter @ None, include_use) => {
265 let use_item = use_item_option.take()?;
266
267 let name = use_item.use_name();
268
269 let source_item = use_item
270 .id
271 .and_then(|id| use_item.get(&id))
272 .or_else(|| {
273 use_item
274 .navigator()
275 .resolve_path(&use_item.source, &mut vec![])
276 })?
277 .with_name(name);
278
279 if use_item.is_glob {
280 match source_item.inner() {
281 ItemEnum::Module(module) => {
282 *id_iter = Some(
283 source_item
284 .id_iter(&module.items)
285 .with_include_use(*include_use),
286 );
287 }
288 ItemEnum::Enum(enum_item) => {
289 *id_iter = Some(
290 source_item
291 .id_iter(&enum_item.variants)
292 .with_include_use(*include_use),
293 );
294 }
295 _ => {
296 return None;
297 }
298 }
299 } else if let ItemEnum::Use(ui) = source_item.inner()
300 && !*include_use
301 {
302 *use_item_option = Some(source_item.build_ref(ui));
303 } else {
304 return Some(source_item);
305 }
306 }
307
308 ChildItems::Use(_, _, _) => return None,
309
310 ChildItems::None => return None,
311 }
312 }
313 }
314}
315
316impl<'a> ChildItems<'a> {
317 pub(crate) fn new(item: DocRef<'a, Item>) -> Self {
318 let parent = ParentRef::from(item);
319 match &item.item().inner {
320 ItemEnum::Module(module) => {
321 Self::Module(item.id_iter(&module.items).with_parent(parent))
322 }
323 ItemEnum::Enum(enum_item) => Self::Enum(
324 item.id_iter(&enum_item.variants).with_parent(parent),
325 item.methods(),
326 ),
327 ItemEnum::Struct(_) => Self::AssociatedMethods(item.methods()),
328 ItemEnum::Use(use_item) => ChildItems::Use(Some(item.build_ref(use_item)), None, false),
329 _ => Self::None,
330 }
331 }
332
333 pub(crate) fn with_use(self) -> Self {
334 match self {
335 ChildItems::AssociatedMethods(method_iter) => {
336 ChildItems::AssociatedMethods(method_iter)
337 }
338 ChildItems::Module(id_iter) => ChildItems::Module(id_iter.with_include_use(true)),
339 ChildItems::Enum(id_iter, method_iter) => {
340 ChildItems::Enum(id_iter.with_include_use(true), method_iter)
341 }
342 ChildItems::Use(item, Some(id_iter), _) => {
343 ChildItems::Use(item, Some(id_iter.with_include_use(true)), true)
344 }
345 ChildItems::Use(item, None, _) => ChildItems::Use(item, None, true),
346 ChildItems::None => ChildItems::None,
347 }
348 }
349}