1use crate::{
2 flattening::NodeMap, object, ExpandedDocument, FlattenedDocument, Id, Indexed, IndexedNode,
3 IndexedObject, Node, Object,
4};
5use smallvec::SmallVec;
6use std::hash::Hash;
7
8pub struct QuadRef<'a, T, B>(
13 pub Option<&'a Id<T, B>>,
14 pub &'a Id<T, B>,
15 pub PropertyRef<'a, T, B>,
16 pub ObjectRef<'a, T, B>,
17);
18
19pub enum PropertyRef<'a, T, B> {
20 Type,
21 Ref(&'a Id<T, B>),
22}
23
24pub enum ObjectRef<'a, T, B> {
25 Object(&'a Object<T, B>),
26 Node(&'a Node<T, B>),
27 Ref(&'a Id<T, B>),
28}
29
30pub trait LdQuads<T, B> {
31 fn quads(&self) -> Quads<T, B>;
32}
33
34impl<T, B> LdQuads<T, B> for ExpandedDocument<T, B> {
35 fn quads(&self) -> Quads<T, B> {
36 let mut stack = SmallVec::new();
37 stack.push(QuadsFrame::IndexedObjectSet(None, self.iter()));
38 Quads { stack }
39 }
40}
41
42impl<T, B> LdQuads<T, B> for FlattenedDocument<T, B> {
43 fn quads(&self) -> Quads<T, B> {
44 let mut stack = SmallVec::new();
45 stack.push(QuadsFrame::IndexedNodeSlice(None, self.iter()));
46 Quads { stack }
47 }
48}
49
50impl<T: Eq + Hash, B: Eq + Hash> LdQuads<T, B> for NodeMap<T, B> {
51 fn quads(&self) -> Quads<T, B> {
52 let mut stack = SmallVec::new();
53
54 for (id, graph) in self {
55 stack.push(QuadsFrame::NodeMapGraph(id, graph.nodes()));
56 }
57
58 Quads { stack }
59 }
60}
61
62const STACK_LEN: usize = 6;
63
64pub struct Quads<'a, T, B> {
65 stack: SmallVec<[QuadsFrame<'a, T, B>; STACK_LEN]>,
66}
67
68enum QuadsFrame<'a, T, B> {
69 NodeMapGraph(
70 Option<&'a Id<T, B>>,
71 crate::flattening::NodeMapGraphNodes<'a, T, B>,
72 ),
73 IndexedObjectSet(
74 Option<&'a Id<T, B>>,
75 indexmap::set::Iter<'a, IndexedObject<T, B>>,
76 ),
77 IndexedNodeSet(
78 Option<&'a Id<T, B>>,
79 indexmap::set::Iter<'a, IndexedNode<T, B>>,
80 ),
81 IndexedObjectSlice(
82 Option<&'a Id<T, B>>,
83 std::slice::Iter<'a, IndexedObject<T, B>>,
84 ),
85 IndexedNodeSlice(
86 Option<&'a Id<T, B>>,
87 std::slice::Iter<'a, IndexedNode<T, B>>,
88 ),
89 NodeTypes(
90 Option<&'a Id<T, B>>,
91 &'a Id<T, B>,
92 std::slice::Iter<'a, Id<T, B>>,
93 ),
94 NodeProperties(
95 Option<&'a Id<T, B>>,
96 &'a Id<T, B>,
97 object::node::properties::Iter<'a, T, B>,
98 ),
99 NodeReverseProperties(
100 Option<&'a Id<T, B>>,
101 &'a Node<T, B>,
102 object::node::reverse_properties::Iter<'a, T, B>,
103 ),
104 NodePropertyObjects(
105 Option<&'a Id<T, B>>,
106 &'a Id<T, B>,
107 &'a Id<T, B>,
108 std::slice::Iter<'a, IndexedObject<T, B>>,
109 ),
110 NodeReversePropertySubjects(
111 Option<&'a Id<T, B>>,
112 &'a Node<T, B>,
113 &'a Id<T, B>,
114 std::slice::Iter<'a, IndexedNode<T, B>>,
115 ),
116}
117
118impl<'a, T, B> Quads<'a, T, B> {
119 fn push_object(&mut self, graph: Option<&'a Id<T, B>>, object: &'a Indexed<Object<T, B>>) {
120 match object.inner() {
121 Object::Node(node) => self.push_node(graph, node),
122 Object::List(objects) => self
123 .stack
124 .push(QuadsFrame::IndexedObjectSlice(graph, objects.iter())),
125 Object::Value(_) => (),
126 }
127 }
128
129 fn push_node(&mut self, graph: Option<&'a Id<T, B>>, node: &'a Node<T, B>) {
130 if let Some(id) = &node.id {
131 if let Some(graph) = node.graph_entry() {
132 self.stack
133 .push(QuadsFrame::IndexedObjectSet(Some(id), graph.iter()))
134 }
135
136 if let Some(included) = node.included_entry() {
137 self.stack
138 .push(QuadsFrame::IndexedNodeSet(graph, included.iter()))
139 }
140
141 if let Some(reverse_properties) = node.reverse_properties_entry() {
142 self.stack.push(QuadsFrame::NodeReverseProperties(
143 graph,
144 node,
145 reverse_properties.iter(),
146 ));
147 }
148
149 self.stack.push(QuadsFrame::NodeProperties(
150 graph,
151 id,
152 node.properties().iter(),
153 ));
154
155 if let Some(types) = &node.types {
156 self.stack
157 .push(QuadsFrame::NodeTypes(graph, id, types.iter()));
158 }
159 }
160 }
161}
162
163impl<'a, T, B> Iterator for Quads<'a, T, B> {
164 type Item = QuadRef<'a, T, B>;
165
166 fn next(&mut self) -> Option<Self::Item> {
167 while let Some(last) = self.stack.last_mut() {
168 match last {
169 QuadsFrame::NodeMapGraph(graph, nodes) => {
170 let graph = *graph;
171 match nodes.next() {
172 Some(node) => self.push_node(graph, node),
173 None => {
174 self.stack.pop();
175 }
176 }
177 }
178 QuadsFrame::IndexedObjectSet(graph, objects) => {
179 let graph = *graph;
180 match objects.next() {
181 Some(object) => self.push_object(graph, object),
182 None => {
183 self.stack.pop();
184 }
185 }
186 }
187 QuadsFrame::IndexedNodeSet(graph, nodes) => {
188 let graph = *graph;
189 match nodes.next() {
190 Some(node) => self.push_node(graph, node),
191 None => {
192 self.stack.pop();
193 }
194 }
195 }
196 QuadsFrame::IndexedObjectSlice(graph, objects) => {
197 let graph = *graph;
198 match objects.next() {
199 Some(object) => self.push_object(graph, object),
200 None => {
201 self.stack.pop();
202 }
203 }
204 }
205 QuadsFrame::IndexedNodeSlice(graph, nodes) => {
206 let graph = *graph;
207 match nodes.next() {
208 Some(node) => self.push_node(graph, node),
209 None => {
210 self.stack.pop();
211 }
212 }
213 }
214 QuadsFrame::NodeTypes(graph, subject, types) => {
215 let (graph, subject) = (*graph, *subject);
216 match types.next() {
217 Some(ty) => {
218 return Some(QuadRef(
219 graph,
220 subject,
221 PropertyRef::Type,
222 ObjectRef::<T, B>::Ref(ty),
223 ))
224 }
225 None => {
226 self.stack.pop();
227 }
228 }
229 }
230 QuadsFrame::NodeProperties(graph, subject, properties) => {
231 let (graph, subject) = (*graph, *subject);
232 match properties.next() {
233 Some((property, objects)) => {
234 self.stack.push(QuadsFrame::NodePropertyObjects(
235 graph,
236 subject,
237 property,
238 objects.iter(),
239 ))
240 }
241 None => {
242 self.stack.pop();
243 }
244 }
245 }
246 QuadsFrame::NodeReverseProperties(graph, object, reverse_properties) => {
247 let (graph, object) = (*graph, *object);
248 match reverse_properties.next() {
249 Some((property, subjects)) => {
250 self.stack.push(QuadsFrame::NodeReversePropertySubjects(
251 graph,
252 object,
253 property,
254 subjects.iter(),
255 ))
256 }
257 None => {
258 self.stack.pop();
259 }
260 }
261 }
262 QuadsFrame::NodePropertyObjects(graph, subject, property, objects) => {
263 let (graph, subject, property) = (*graph, *subject, *property);
264 match objects.next() {
265 Some(object) => {
266 self.push_object(graph, object);
267 return Some(QuadRef(
268 graph,
269 subject,
270 PropertyRef::Ref(property),
271 ObjectRef::Object(object),
272 ));
273 }
274 None => {
275 self.stack.pop();
276 }
277 }
278 }
279 QuadsFrame::NodeReversePropertySubjects(graph, object, property, subjects) => {
280 let (graph, object, property) = (*graph, *object, *property);
281 match subjects.next() {
282 Some(subject) => {
283 self.push_node(graph, subject.inner());
284 if let Some(id) = &subject.id {
285 return Some(QuadRef(
286 graph,
287 id,
288 PropertyRef::Ref(property),
289 ObjectRef::Node(object),
290 ));
291 }
292 }
293 None => {
294 self.stack.pop();
295 }
296 }
297 }
298 }
299 }
300
301 None
302 }
303}