json_ld_core/
quad.rs

1use crate::{
2	flattening::NodeMap, object, ExpandedDocument, FlattenedDocument, Id, Indexed, IndexedNode,
3	IndexedObject, Node, Object,
4};
5use smallvec::SmallVec;
6use std::hash::Hash;
7
8/// JSON-LD Quad.
9///
10/// This is different from an RDF Quad since the object (last element) is a JSON-LD object.
11/// A JSON-LD Quad can correspond to multiple RDF Quads.
12pub 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}