cynic_parser/executable/
iter.rs

1use std::{fmt, iter::FusedIterator};
2
3use crate::common::{IdOperations, IdRange, IdRangeIter};
4
5use super::{ExecutableDocument, ExecutableId};
6
7pub trait IdReader {
8    type Id: ExecutableId;
9    type Reader<'a>;
10
11    fn new(id: Self::Id, document: &'_ ExecutableDocument) -> Self::Reader<'_>;
12}
13
14/// Iterator for readers in the executable module
15///
16/// T indicates the type that will be yielded by the Iterator
17#[derive(Clone)]
18pub struct Iter<'a, T>
19where
20    T: IdReader,
21{
22    ids: IdRangeIter<T::Id>,
23    document: &'a super::ExecutableDocument,
24}
25
26impl<'a, T> Iter<'a, T>
27where
28    T: IdReader,
29{
30    pub(crate) fn new(range: IdRange<T::Id>, document: &'a super::ExecutableDocument) -> Self
31    where
32        T::Id: IdOperations,
33    {
34        Iter {
35            ids: range.into_iter(),
36            document,
37        }
38    }
39
40    pub fn ids(&self) -> IdRange<T::Id> {
41        self.ids.current_range()
42    }
43
44    pub fn with_ids(&self) -> IdIter<'a, T> {
45        let Iter { ids, document } = self;
46
47        IdIter {
48            ids: ids.clone(),
49            document,
50        }
51    }
52}
53
54impl<'a, T> Iterator for Iter<'a, T>
55where
56    T: IdReader,
57    T::Id: IdOperations,
58{
59    type Item = T::Reader<'a>;
60
61    fn next(&mut self) -> Option<Self::Item> {
62        Some(T::new(self.ids.next()?, self.document))
63    }
64
65    fn size_hint(&self) -> (usize, Option<usize>) {
66        self.ids.size_hint()
67    }
68}
69
70impl<T> ExactSizeIterator for Iter<'_, T>
71where
72    T: IdReader,
73    T::Id: IdOperations,
74{
75}
76
77impl<T> FusedIterator for Iter<'_, T>
78where
79    T: IdReader,
80    T::Id: IdOperations,
81{
82}
83
84impl<T> DoubleEndedIterator for Iter<'_, T>
85where
86    T: IdReader,
87    T::Id: IdOperations,
88{
89    // Required method
90    fn next_back(&mut self) -> Option<Self::Item> {
91        Some(T::new(self.ids.next_back()?, self.document))
92    }
93}
94
95impl<T> fmt::Debug for Iter<'_, T>
96where
97    T: IdReader + Copy,
98    Self: Iterator,
99    <Self as Iterator>::Item: fmt::Debug,
100{
101    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102        f.debug_list().entries(self.clone()).finish()
103    }
104}
105
106/// Iterator over an Id & a Reader for that Id
107///
108/// T indicates the reader type that will be yielded by the Iterator
109#[derive(Clone)]
110pub struct IdIter<'a, T>
111where
112    T: IdReader,
113{
114    ids: IdRangeIter<T::Id>,
115    document: &'a super::ExecutableDocument,
116}
117
118impl<'a, T> Iterator for IdIter<'a, T>
119where
120    T: IdReader,
121    T::Id: IdOperations,
122{
123    type Item = (T::Id, <T::Id as ExecutableId>::Reader<'a>);
124
125    fn next(&mut self) -> Option<Self::Item> {
126        let next = self.ids.next()?;
127
128        Some((next, self.document.read(next)))
129    }
130
131    fn size_hint(&self) -> (usize, Option<usize>) {
132        self.ids.size_hint()
133    }
134}
135
136impl<T> ExactSizeIterator for IdIter<'_, T>
137where
138    T: IdReader,
139    T::Id: IdOperations,
140{
141}
142
143impl<T> FusedIterator for IdIter<'_, T>
144where
145    T: IdReader,
146    T::Id: IdOperations,
147{
148}
149
150impl<T> DoubleEndedIterator for IdIter<'_, T>
151where
152    T: IdReader,
153    T::Id: IdOperations,
154{
155    // Required method
156    fn next_back(&mut self) -> Option<Self::Item> {
157        let next = self.ids.next_back()?;
158
159        Some((next, self.document.read(next)))
160    }
161}
162
163impl<T> fmt::Debug for IdIter<'_, T>
164where
165    T: IdReader + Copy,
166    Self: Iterator,
167    <Self as Iterator>::Item: fmt::Debug,
168{
169    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170        f.debug_list().entries(self.clone()).finish()
171    }
172}