json_ld_core/object/node/
mod.rs

1use super::{InvalidExpandedJson, Traverse, TryFromJson, TryFromJsonObject};
2use crate::{object, utils, Id, Indexed, IndexedObject, Object, Objects, Relabel, Term};
3use contextual::{IntoRefWithContext, WithContext};
4use educe::Educe;
5use indexmap::IndexSet;
6use iref::IriBuf;
7use json_ld_syntax::{IntoJson, IntoJsonWithContext, Keyword};
8use rdf_types::{BlankIdBuf, Generator, Subject, Vocabulary, VocabularyMut};
9use std::convert::TryFrom;
10use std::hash::{Hash, Hasher};
11
12pub mod multiset;
13pub mod properties;
14pub mod reverse_properties;
15
16pub use multiset::Multiset;
17pub use properties::Properties;
18pub use reverse_properties::ReverseProperties;
19
20pub type Graph<T, B> = IndexSet<IndexedObject<T, B>>;
21
22pub type Included<T, B> = IndexSet<IndexedNode<T, B>>;
23
24pub type IndexedNode<T = IriBuf, B = BlankIdBuf> = Indexed<Node<T, B>>;
25
26/// Node object.
27///
28/// A node object represents zero or more properties of a node in the graph serialized by a JSON-LD document.
29/// A node is defined by its identifier (`@id` field), types, properties and reverse properties.
30/// In addition, a node may represent a graph (`@graph field`) and includes nodes
31/// (`@included` field).
32// NOTE it may be better to use BTreeSet instead of HashSet to have some ordering?
33//      in which case the Json bound should be lifted.
34#[derive(Educe, Debug, Clone)]
35#[educe(Eq(bound = "T: Eq + Hash, B: Eq + Hash"))]
36pub struct Node<T = IriBuf, B = BlankIdBuf> {
37	/// Identifier.
38	///
39	/// This is the `@id` field.
40	pub id: Option<Id<T, B>>,
41
42	/// Types.
43	///
44	/// This is the `@type` field.
45	pub types: Option<Vec<Id<T, B>>>,
46
47	/// Associated graph.
48	///
49	/// This is the `@graph` field.
50	pub graph: Option<Graph<T, B>>,
51
52	/// Included nodes.
53	///
54	/// This is the `@included` field.
55	pub included: Option<Included<T, B>>,
56
57	/// Properties.
58	///
59	/// Any non-keyword field.
60	pub properties: Properties<T, B>,
61
62	/// Reverse properties.
63	///
64	/// This is the `@reverse` field.
65	pub reverse_properties: Option<ReverseProperties<T, B>>,
66}
67
68impl<T, B> Default for Node<T, B> {
69	#[inline(always)]
70	fn default() -> Self {
71		Self::new()
72	}
73}
74
75impl<T, B> Node<T, B> {
76	/// Creates a new empty node.
77	#[inline(always)]
78	pub fn new() -> Self {
79		Self {
80			id: None,
81			types: None,
82			graph: None,
83			included: None,
84			properties: Properties::new(),
85			reverse_properties: None,
86		}
87	}
88
89	/// Creates a new empty node with the given id.
90	#[inline(always)]
91	pub fn with_id(id: Id<T, B>) -> Self {
92		Self {
93			id: Some(id),
94			types: None,
95			graph: None,
96			included: None,
97			properties: Properties::new(),
98			reverse_properties: None,
99		}
100	}
101
102	/// Creates a new graph node.
103	pub fn new_graph(id: Id<T, B>, graph: Graph<T, B>) -> Self {
104		Self {
105			id: Some(id),
106			types: None,
107			graph: Some(graph),
108			included: None,
109			properties: Properties::new(),
110			reverse_properties: None,
111		}
112	}
113
114	/// Returns a mutable reference to the reverse properties of the node.
115	///
116	/// If no `@reverse` entry is present, one is created.
117	#[inline(always)]
118	pub fn reverse_properties_mut_or_default(&mut self) -> &mut ReverseProperties<T, B> {
119		self.reverse_properties
120			.get_or_insert_with(ReverseProperties::default)
121	}
122
123	/// Returns a mutable reference to the included nodes.
124	///
125	/// If no `@included` entry is present, one is created.
126	#[inline(always)]
127	pub fn included_mut_or_default(&mut self) -> &mut Included<T, B> {
128		self.included.get_or_insert_with(Included::default)
129	}
130
131	/// Assigns an identifier to this node and every other node included in this
132	/// one using the given `generator`.
133	pub fn identify_all_with<V: Vocabulary<Iri = T, BlankId = B>, G: Generator<V>>(
134		&mut self,
135		vocabulary: &mut V,
136		generator: &mut G,
137	) where
138		T: Eq + Hash,
139		B: Eq + Hash,
140	{
141		if self.id.is_none() {
142			self.id = Some(generator.next(vocabulary).into())
143		}
144
145		if let Some(graph) = self.graph_mut() {
146			*graph = std::mem::take(graph)
147				.into_iter()
148				.map(|mut o| {
149					o.identify_all_with(vocabulary, generator);
150					o
151				})
152				.collect();
153		}
154
155		if let Some(included) = self.included_mut() {
156			*included = std::mem::take(included)
157				.into_iter()
158				.map(|mut n| {
159					n.identify_all_with(vocabulary, generator);
160					n
161				})
162				.collect();
163		}
164
165		for (_, objects) in self.properties_mut() {
166			for object in objects {
167				object.identify_all_with(vocabulary, generator);
168			}
169		}
170
171		if let Some(reverse_properties) = self.reverse_properties_mut() {
172			for (_, nodes) in reverse_properties.iter_mut() {
173				for node in nodes {
174					node.identify_all_with(vocabulary, generator);
175				}
176			}
177		}
178	}
179
180	/// Assigns an identifier to this node and every other node included in this one using the given `generator`.
181	pub fn identify_all<G: Generator>(&mut self, generator: &mut G)
182	where
183		T: Eq + Hash,
184		B: Eq + Hash,
185		(): Vocabulary<Iri = T, BlankId = B>,
186	{
187		self.identify_all_with(&mut (), generator)
188	}
189
190	/// Puts this node object literals into canonical form using the given
191	/// `buffer`.
192	///
193	/// The buffer is used to compute the canonical form of numbers.
194	pub fn canonicalize_with(&mut self, buffer: &mut ryu_js::Buffer) {
195		for (_, objects) in self.properties_mut() {
196			for object in objects {
197				object.canonicalize_with(buffer)
198			}
199		}
200
201		if let Some(reverse_properties) = self.reverse_properties_mut() {
202			for (_, nodes) in reverse_properties.iter_mut() {
203				for node in nodes {
204					node.canonicalize_with(buffer)
205				}
206			}
207		}
208	}
209
210	/// Puts this node object literals into canonical form.
211	pub fn canonicalize(&mut self) {
212		let mut buffer = ryu_js::Buffer::new();
213		self.canonicalize_with(&mut buffer)
214	}
215
216	/// Get the node's as an IRI if possible.
217	///
218	/// Returns the node's IRI id if any. Returns `None` otherwise.
219	#[inline(always)]
220	pub fn as_iri(&self) -> Option<&T> {
221		if let Some(id) = &self.id {
222			id.as_iri()
223		} else {
224			None
225		}
226	}
227
228	/// Get the node's id, is any, as a string slice.
229	///
230	/// Returns `None` if the node has no `@id` field.
231	#[inline(always)]
232	pub fn as_str(&self) -> Option<&str>
233	where
234		T: AsRef<str>,
235	{
236		match self.as_iri() {
237			Some(iri) => Some(iri.as_ref()),
238			None => None,
239		}
240	}
241
242	/// Get the list of the node's types.
243	#[inline(always)]
244	pub fn types(&self) -> &[Id<T, B>] {
245		match self.types.as_ref() {
246			Some(entry) => entry,
247			None => &[],
248		}
249	}
250
251	/// Returns a mutable reference to the node's types.
252	#[inline(always)]
253	pub fn types_mut(&mut self) -> &mut [Id<T, B>] {
254		match self.types.as_mut() {
255			Some(entry) => entry,
256			None => &mut [],
257		}
258	}
259
260	pub fn types_mut_or_default(&mut self) -> &mut Vec<Id<T, B>> {
261		self.types.get_or_insert_with(Vec::new)
262	}
263
264	pub fn types_mut_or_insert(&mut self, value: Vec<Id<T, B>>) -> &mut Vec<Id<T, B>> {
265		self.types.get_or_insert(value)
266	}
267
268	pub fn types_mut_or_insert_with(
269		&mut self,
270		f: impl FnOnce() -> Vec<Id<T, B>>,
271	) -> &mut Vec<Id<T, B>> {
272		self.types.get_or_insert_with(f)
273	}
274
275	/// Checks if the node has the given type.
276	#[inline]
277	pub fn has_type<U>(&self, ty: &U) -> bool
278	where
279		Id<T, B>: PartialEq<U>,
280	{
281		for self_ty in self.types() {
282			if self_ty == ty {
283				return true;
284			}
285		}
286
287		false
288	}
289
290	/// Tests if the node is empty.
291	///
292	/// It is empty is every field other than `@id` is empty.
293	#[inline]
294	pub fn is_empty(&self) -> bool {
295		self.types.is_none()
296			&& self.graph.is_none()
297			&& self.included.is_none()
298			&& self.properties.is_empty()
299			&& self.reverse_properties.is_none()
300	}
301
302	/// Tests if the node is a graph object (has a `@graph` field, and optionally an `@id` field).
303	/// Note that node objects may have a @graph entry,
304	/// but are not considered graph objects if they include any other entries other than `@id`.
305	#[inline]
306	pub fn is_graph(&self) -> bool {
307		self.graph.is_some()
308			&& self.types.is_none()
309			&& self.included.is_none()
310			&& self.properties.is_empty()
311			&& self.reverse_properties.is_none()
312	}
313
314	/// Tests if the node is a simple graph object (a graph object without `@id` field)
315	#[inline(always)]
316	pub fn is_simple_graph(&self) -> bool {
317		self.id.is_none() && self.is_graph()
318	}
319
320	/// If the node is a graph object, get the graph.
321	#[inline(always)]
322	pub fn graph(&self) -> Option<&Graph<T, B>> {
323		self.graph.as_ref()
324	}
325
326	/// If the node is a graph object, get the mutable graph.
327	#[inline(always)]
328	pub fn graph_mut(&mut self) -> Option<&mut Graph<T, B>> {
329		self.graph.as_mut()
330	}
331
332	/// If the node is a graph object, get the graph.
333	#[inline(always)]
334	pub fn graph_entry(&self) -> Option<&Graph<T, B>> {
335		self.graph.as_ref()
336	}
337
338	/// If the node is a graph object, get the mutable graph.
339	#[inline(always)]
340	pub fn graph_entry_mut(&mut self) -> Option<&mut Graph<T, B>> {
341		self.graph.as_mut()
342	}
343
344	/// Set the graph.
345	#[inline(always)]
346	pub fn set_graph_entry(&mut self, graph: Option<Graph<T, B>>) {
347		self.graph = graph
348	}
349
350	/// Get the set of nodes included by this node.
351	///
352	/// This correspond to the `@included` field in the JSON representation.
353	#[inline(always)]
354	pub fn included_entry(&self) -> Option<&Included<T, B>> {
355		self.included.as_ref()
356	}
357
358	/// Get the mutable set of nodes included by this node.
359	///
360	/// This correspond to the `@included` field in the JSON representation.
361	#[inline(always)]
362	pub fn included_entry_mut(&mut self) -> Option<&mut Included<T, B>> {
363		self.included.as_mut()
364	}
365
366	/// Returns a reference to the set of `@included` nodes.
367	pub fn included(&self) -> Option<&Included<T, B>> {
368		self.included.as_ref()
369	}
370
371	/// Returns a mutable reference to the set of `@included` nodes.
372	pub fn included_mut(&mut self) -> Option<&mut Included<T, B>> {
373		self.included.as_mut()
374	}
375
376	/// Set the set of nodes included by the node.
377	#[inline(always)]
378	pub fn set_included(&mut self, included: Option<Included<T, B>>) {
379		self.included = included
380	}
381
382	/// Returns a reference to the properties of the node.
383	#[inline(always)]
384	pub fn properties(&self) -> &Properties<T, B> {
385		&self.properties
386	}
387
388	/// Returns a mutable reference to the properties of the node.
389	#[inline(always)]
390	pub fn properties_mut(&mut self) -> &mut Properties<T, B> {
391		&mut self.properties
392	}
393
394	/// Returns a reference to the properties of the node.
395	#[inline(always)]
396	pub fn reverse_properties(&self) -> Option<&ReverseProperties<T, B>> {
397		self.reverse_properties.as_ref()
398	}
399
400	/// Returns a reference to the reverse properties of the node.
401	#[inline(always)]
402	pub fn reverse_properties_entry(&self) -> Option<&ReverseProperties<T, B>> {
403		self.reverse_properties.as_ref()
404	}
405
406	/// Returns a mutable reference to the reverse properties of the node.
407	#[inline(always)]
408	pub fn reverse_properties_mut(&mut self) -> Option<&mut ReverseProperties<T, B>> {
409		self.reverse_properties.as_mut()
410	}
411
412	pub fn set_reverse_properties(&mut self, reverse_properties: Option<ReverseProperties<T, B>>) {
413		self.reverse_properties = reverse_properties
414	}
415
416	/// Tests if the node is an unnamed graph object.
417	///
418	/// Returns `true` is the only field of the object is a `@graph` field.
419	/// Returns `false` otherwise.
420	#[inline]
421	pub fn is_unnamed_graph(&self) -> bool {
422		self.graph.is_some()
423			&& self.id.is_none()
424			&& self.types.is_none()
425			&& self.included.is_none()
426			&& self.properties.is_empty()
427			&& self.reverse_properties.is_none()
428	}
429
430	/// Returns the node as an unnamed graph, if it is one.
431	///
432	/// The unnamed graph is returned as a set of indexed objects.
433	/// Fails and returns itself if the node is *not* an unnamed graph.
434	#[allow(clippy::result_large_err)]
435	#[inline(always)]
436	pub fn into_unnamed_graph(self) -> Result<Graph<T, B>, Self> {
437		if self.is_unnamed_graph() {
438			Ok(self.graph.unwrap())
439		} else {
440			Err(self)
441		}
442	}
443
444	pub fn traverse(&self) -> Traverse<T, B> {
445		Traverse::new(Some(super::FragmentRef::Node(self)))
446	}
447
448	#[inline(always)]
449	pub fn count(&self, f: impl FnMut(&super::FragmentRef<T, B>) -> bool) -> usize {
450		self.traverse().filter(f).count()
451	}
452
453	pub fn entries(&self) -> Entries<T, B> {
454		Entries {
455			id: self.id.as_ref(),
456			type_: self.types.as_deref(),
457			graph: self.graph.as_ref(),
458			included: self.included.as_ref(),
459			reverse: self.reverse_properties.as_ref(),
460			properties: self.properties.iter(),
461		}
462	}
463
464	/// Map the identifiers present in this list (recursively).
465	pub fn map_ids<U, C>(
466		self,
467		mut map_iri: impl FnMut(T) -> U,
468		mut map_id: impl FnMut(Id<T, B>) -> Id<U, C>,
469	) -> Node<U, C>
470	where
471		U: Eq + Hash,
472		C: Eq + Hash,
473	{
474		self.map_ids_with(&mut map_iri, &mut map_id)
475	}
476
477	pub(crate) fn map_ids_with<U, C>(
478		self,
479		map_iri: &mut impl FnMut(T) -> U,
480		map_id: &mut impl FnMut(Id<T, B>) -> Id<U, C>,
481	) -> Node<U, C>
482	where
483		U: Eq + Hash,
484		C: Eq + Hash,
485	{
486		Node {
487			id: self.id.map(&mut *map_id),
488			types: self
489				.types
490				.map(|t| t.into_iter().map(&mut *map_id).collect()),
491			graph: self.graph.map(|g| {
492				g.into_iter()
493					.map(|o| o.map_inner(|o| o.map_ids_with(map_iri, map_id)))
494					.collect()
495			}),
496			included: self.included.map(|i| {
497				i.into_iter()
498					.map(|o| o.map_inner(|o| o.map_ids_with(map_iri, map_id)))
499					.collect()
500			}),
501			properties: self
502				.properties
503				.into_iter()
504				.map(|(id, values)| {
505					(
506						map_id(id),
507						values
508							.into_iter()
509							.map(|o| o.map_inner(|o| o.map_ids_with(map_iri, map_id)))
510							.collect::<Vec<_>>(),
511					)
512				})
513				.collect(),
514			reverse_properties: self.reverse_properties.map(|r| {
515				r.into_iter()
516					.map(|(id, values)| {
517						(
518							map_id(id),
519							values
520								.into_iter()
521								.map(|o| o.map_inner(|o| o.map_ids_with(map_iri, map_id)))
522								.collect::<Vec<_>>(),
523						)
524					})
525					.collect()
526			}),
527		}
528	}
529}
530
531impl<T: Eq + Hash, B: Eq + Hash> Node<T, B> {
532	/// Checks if the node object has the given term as key.
533	///
534	/// # Example
535	/// ```
536	/// # use json_ld_syntax::Keyword;
537	/// # use json_ld_core::Term;
538	/// # let node: json_ld_core::Node = json_ld_core::Node::new();
539	///
540	/// // Checks if the JSON object representation of the node has an `@id` key.
541	/// if node.has_key(&Term::Keyword(Keyword::Id)) {
542	///   // ...
543	/// }
544	/// ```
545	#[inline(always)]
546	pub fn has_key(&self, key: &Term<T, B>) -> bool {
547		match key {
548			Term::Keyword(Keyword::Id) => self.id.is_some(),
549			Term::Keyword(Keyword::Type) => self.types.is_some(),
550			Term::Keyword(Keyword::Graph) => self.graph.is_some(),
551			Term::Keyword(Keyword::Included) => self.included.is_some(),
552			Term::Keyword(Keyword::Reverse) => self.reverse_properties.is_some(),
553			Term::Id(prop) => self.properties.contains(prop),
554			_ => false,
555		}
556	}
557
558	/// Get all the objects associated to the node with the given property.
559	#[inline(always)]
560	pub fn get<'a, Q: ?Sized + Hash + indexmap::Equivalent<Id<T, B>>>(
561		&self,
562		prop: &Q,
563	) -> Objects<T, B>
564	where
565		T: 'a,
566	{
567		self.properties.get(prop)
568	}
569
570	/// Get one of the objects associated to the node with the given property.
571	///
572	/// If multiple objects are attached to the node with this property, there are no guaranties
573	/// on which object will be returned.
574	#[inline(always)]
575	pub fn get_any<'a, Q: ?Sized + Hash + indexmap::Equivalent<Id<T, B>>>(
576		&self,
577		prop: &Q,
578	) -> Option<&IndexedObject<T, B>>
579	where
580		T: 'a,
581	{
582		self.properties.get_any(prop)
583	}
584
585	/// Associates the given object to the node through the given property.
586	#[inline(always)]
587	pub fn insert(&mut self, prop: Id<T, B>, value: IndexedObject<T, B>) {
588		self.properties.insert(prop, value)
589	}
590
591	/// Associates all the given objects to the node through the given property.
592	///
593	/// If there already exists objects associated to the given reverse property,
594	/// `reverse_value` is added to the list. Duplicate objects are not removed.
595	#[inline(always)]
596	pub fn insert_all<Objects: Iterator<Item = IndexedObject<T, B>>>(
597		&mut self,
598		prop: Id<T, B>,
599		values: Objects,
600	) {
601		self.properties.insert_all(prop, values)
602	}
603
604	pub fn reverse_properties_or_insert(
605		&mut self,
606		props: ReverseProperties<T, B>,
607	) -> &mut ReverseProperties<T, B> {
608		self.reverse_properties.get_or_insert(props)
609	}
610
611	pub fn reverse_properties_or_default(&mut self) -> &mut ReverseProperties<T, B> {
612		self.reverse_properties
613			.get_or_insert_with(ReverseProperties::default)
614	}
615
616	pub fn reverse_properties_or_insert_with(
617		&mut self,
618		f: impl FnOnce() -> ReverseProperties<T, B>,
619	) -> &mut ReverseProperties<T, B> {
620		self.reverse_properties.get_or_insert_with(f)
621	}
622
623	/// Equivalence operator.
624	///
625	/// Equivalence is different from equality for anonymous objects.
626	/// Anonymous node objects have an implicit unlabeled blank nodes and thus never equivalent.
627	pub fn equivalent(&self, other: &Self) -> bool {
628		if self.id.is_some() && other.id.is_some() {
629			self == other
630		} else {
631			false
632		}
633	}
634}
635
636impl<T, B> Relabel<T, B> for Node<T, B> {
637	fn relabel_with<N: Vocabulary<Iri = T, BlankId = B>, G: Generator<N>>(
638		&mut self,
639		vocabulary: &mut N,
640		generator: &mut G,
641		relabeling: &mut hashbrown::HashMap<B, Subject<T, B>>,
642	) where
643		T: Clone + Eq + Hash,
644		B: Clone + Eq + Hash,
645	{
646		self.id = match self.id.take() {
647			Some(Id::Valid(Subject::Blank(b))) => {
648				let value = relabeling
649					.entry(b)
650					.or_insert_with(|| generator.next(vocabulary))
651					.clone();
652				Some(value.into())
653			}
654			None => {
655				let value = generator.next(vocabulary);
656				Some(value.into())
657			}
658			id => id,
659		};
660
661		for ty in self.types_mut() {
662			if let Some(b) = ty.as_blank().cloned() {
663				*ty = relabeling
664					.entry(b)
665					.or_insert_with(|| generator.next(vocabulary))
666					.clone()
667					.into();
668			}
669		}
670
671		if let Some(graph) = self.graph_mut() {
672			*graph = std::mem::take(graph)
673				.into_iter()
674				.map(|mut o| {
675					o.relabel_with(vocabulary, generator, relabeling);
676					o
677				})
678				.collect();
679		}
680
681		if let Some(included) = self.included_mut() {
682			*included = std::mem::take(included)
683				.into_iter()
684				.map(|mut n| {
685					n.relabel_with(vocabulary, generator, relabeling);
686					n
687				})
688				.collect();
689		}
690
691		for (_, objects) in self.properties_mut() {
692			for object in objects {
693				object.relabel_with(vocabulary, generator, relabeling);
694			}
695		}
696
697		if let Some(reverse_properties) = self.reverse_properties_mut() {
698			for (_, nodes) in reverse_properties.iter_mut() {
699				for node in nodes {
700					node.relabel_with(vocabulary, generator, relabeling);
701				}
702			}
703		}
704	}
705}
706
707impl<T: Eq + Hash, B: Eq + Hash> PartialEq for Node<T, B> {
708	fn eq(&self, other: &Self) -> bool {
709		self.id.eq(&other.id)
710			&& multiset::compare_unordered_opt(self.types.as_deref(), other.types.as_deref())
711			&& self.graph.as_ref() == other.graph.as_ref()
712			&& self.included.as_ref() == other.included.as_ref()
713			&& self.properties.eq(&other.properties)
714			&& self.reverse_properties.eq(&other.reverse_properties)
715	}
716}
717
718impl<T, B> Indexed<Node<T, B>> {
719	pub fn entries(&self) -> IndexedEntries<T, B> {
720		IndexedEntries {
721			index: self.index(),
722			inner: self.inner().entries(),
723		}
724	}
725}
726
727impl<T: Eq + Hash, B: Eq + Hash> Indexed<Node<T, B>> {
728	pub fn equivalent(&self, other: &Self) -> bool {
729		self.index() == other.index() && self.inner().equivalent(other.inner())
730	}
731}
732
733#[derive(Educe, PartialEq, Eq)]
734#[educe(Clone, Copy)]
735pub enum EntryKeyRef<'a, T, B> {
736	Id,
737	Type,
738	Graph,
739	Included,
740	Reverse,
741	Property(&'a Id<T, B>),
742}
743
744impl<'a, T, B> EntryKeyRef<'a, T, B> {
745	pub fn into_keyword(self) -> Option<Keyword> {
746		match self {
747			Self::Id => Some(Keyword::Id),
748			Self::Type => Some(Keyword::Type),
749			Self::Graph => Some(Keyword::Graph),
750			Self::Included => Some(Keyword::Included),
751			Self::Reverse => Some(Keyword::Reverse),
752			Self::Property(_) => None,
753		}
754	}
755
756	pub fn as_keyword(&self) -> Option<Keyword> {
757		self.into_keyword()
758	}
759
760	pub fn into_str(self) -> &'a str
761	where
762		T: AsRef<str>,
763		B: AsRef<str>,
764	{
765		match self {
766			Self::Id => "@id",
767			Self::Type => "@type",
768			Self::Graph => "@graph",
769			Self::Included => "@included",
770			Self::Reverse => "@reverse",
771			Self::Property(p) => p.as_str(),
772		}
773	}
774
775	pub fn as_str(&self) -> &'a str
776	where
777		T: AsRef<str>,
778		B: AsRef<str>,
779	{
780		self.into_str()
781	}
782}
783
784impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> IntoRefWithContext<'a, str, N>
785	for EntryKeyRef<'a, T, B>
786{
787	fn into_ref_with(self, vocabulary: &'a N) -> &'a str {
788		match self {
789			EntryKeyRef::Id => "@id",
790			EntryKeyRef::Type => "@type",
791			EntryKeyRef::Graph => "@graph",
792			EntryKeyRef::Included => "@included",
793			EntryKeyRef::Reverse => "@reverse",
794			EntryKeyRef::Property(p) => p.with(vocabulary).as_str(),
795		}
796	}
797}
798
799#[derive(Educe)]
800#[educe(Clone, Copy)]
801pub enum EntryValueRef<'a, T, B> {
802	Id(&'a Id<T, B>),
803	Type(&'a [Id<T, B>]),
804	Graph(&'a IndexSet<IndexedObject<T, B>>),
805	Included(&'a IndexSet<IndexedNode<T, B>>),
806	Reverse(&'a ReverseProperties<T, B>),
807	Property(&'a [IndexedObject<T, B>]),
808}
809
810impl<'a, T, B> EntryValueRef<'a, T, B> {
811	pub fn is_json_array(&self) -> bool {
812		matches!(
813			self,
814			Self::Type(_) | Self::Graph(_) | Self::Included(_) | Self::Property(_)
815		)
816	}
817
818	pub fn is_json_object(&self) -> bool {
819		matches!(self, Self::Reverse(_))
820	}
821
822	fn sub_fragments(&self) -> SubFragments<'a, T, B> {
823		match self {
824			Self::Type(l) => SubFragments::Type(l.iter()),
825			Self::Graph(g) => SubFragments::Graph(g.iter()),
826			Self::Included(i) => SubFragments::Included(i.iter()),
827			Self::Reverse(r) => SubFragments::Reverse(r.iter()),
828			Self::Property(p) => SubFragments::Property(p.iter()),
829			_ => SubFragments::None,
830		}
831	}
832}
833
834#[derive(Educe)]
835#[educe(Clone, Copy)]
836pub enum EntryRef<'a, T, B> {
837	Id(&'a Id<T, B>),
838	Type(&'a [Id<T, B>]),
839	Graph(&'a Graph<T, B>),
840	Included(&'a Included<T, B>),
841	Reverse(&'a ReverseProperties<T, B>),
842	Property(&'a Id<T, B>, &'a [IndexedObject<T, B>]),
843}
844
845impl<'a, T, B> EntryRef<'a, T, B> {
846	pub fn into_key(self) -> EntryKeyRef<'a, T, B> {
847		match self {
848			Self::Id(_) => EntryKeyRef::Id,
849			Self::Type(_) => EntryKeyRef::Type,
850			Self::Graph(_) => EntryKeyRef::Graph,
851			Self::Included(_) => EntryKeyRef::Included,
852			Self::Reverse(_) => EntryKeyRef::Reverse,
853			Self::Property(k, _) => EntryKeyRef::Property(k),
854		}
855	}
856
857	pub fn key(&self) -> EntryKeyRef<'a, T, B> {
858		self.into_key()
859	}
860
861	pub fn into_value(self) -> EntryValueRef<'a, T, B> {
862		match self {
863			Self::Id(v) => EntryValueRef::Id(v),
864			Self::Type(v) => EntryValueRef::Type(v),
865			Self::Graph(v) => EntryValueRef::Graph(v),
866			Self::Included(v) => EntryValueRef::Included(v),
867			Self::Reverse(v) => EntryValueRef::Reverse(v),
868			Self::Property(_, v) => EntryValueRef::Property(v),
869		}
870	}
871
872	pub fn value(&self) -> EntryValueRef<'a, T, B> {
873		self.into_value()
874	}
875
876	pub fn into_key_value(self) -> (EntryKeyRef<'a, T, B>, EntryValueRef<'a, T, B>) {
877		match self {
878			Self::Id(v) => (EntryKeyRef::Id, EntryValueRef::Id(v)),
879			Self::Type(v) => (EntryKeyRef::Type, EntryValueRef::Type(v)),
880			Self::Graph(v) => (EntryKeyRef::Graph, EntryValueRef::Graph(v)),
881			Self::Included(v) => (EntryKeyRef::Included, EntryValueRef::Included(v)),
882			Self::Reverse(v) => (EntryKeyRef::Reverse, EntryValueRef::Reverse(v)),
883			Self::Property(k, v) => (EntryKeyRef::Property(k), EntryValueRef::Property(v)),
884		}
885	}
886
887	pub fn as_key_value(&self) -> (EntryKeyRef<'a, T, B>, EntryValueRef<'a, T, B>) {
888		match self {
889			Self::Id(v) => (EntryKeyRef::Id, EntryValueRef::Id(*v)),
890			Self::Type(v) => (EntryKeyRef::Type, EntryValueRef::Type(v)),
891			Self::Graph(v) => (EntryKeyRef::Graph, EntryValueRef::Graph(*v)),
892			Self::Included(v) => (EntryKeyRef::Included, EntryValueRef::Included(*v)),
893			Self::Reverse(v) => (EntryKeyRef::Reverse, EntryValueRef::Reverse(*v)),
894			Self::Property(k, v) => (EntryKeyRef::Property(*k), EntryValueRef::Property(v)),
895		}
896	}
897}
898
899#[derive(Educe)]
900#[educe(Clone)]
901pub struct Entries<'a, T, B> {
902	id: Option<&'a Id<T, B>>,
903	type_: Option<&'a [Id<T, B>]>,
904	graph: Option<&'a Graph<T, B>>,
905	included: Option<&'a Included<T, B>>,
906	reverse: Option<&'a ReverseProperties<T, B>>,
907	properties: properties::Iter<'a, T, B>,
908}
909
910impl<'a, T, B> Iterator for Entries<'a, T, B> {
911	type Item = EntryRef<'a, T, B>;
912
913	fn size_hint(&self) -> (usize, Option<usize>) {
914		let mut len = self.properties.len();
915
916		if self.id.is_some() {
917			len += 1
918		}
919
920		if self.type_.is_some() {
921			len += 1
922		}
923
924		if self.graph.is_some() {
925			len += 1
926		}
927
928		if self.included.is_some() {
929			len += 1
930		}
931
932		if self.reverse.is_some() {
933			len += 1
934		}
935
936		(len, Some(len))
937	}
938
939	fn next(&mut self) -> Option<Self::Item> {
940		self.id.take().map(EntryRef::Id).or_else(|| {
941			self.type_.take().map(EntryRef::Type).or_else(|| {
942				self.graph.take().map(EntryRef::Graph).or_else(|| {
943					self.included.take().map(EntryRef::Included).or_else(|| {
944						self.reverse.take().map(EntryRef::Reverse).or_else(|| {
945							self.properties
946								.next()
947								.map(|(k, v)| EntryRef::Property(k, v))
948						})
949					})
950				})
951			})
952		})
953	}
954}
955
956impl<'a, T, B> ExactSizeIterator for Entries<'a, T, B> {}
957
958#[derive(Educe)]
959#[educe(Clone)]
960pub struct IndexedEntries<'a, T, B> {
961	index: Option<&'a str>,
962	inner: Entries<'a, T, B>,
963}
964
965impl<'a, T, B> Iterator for IndexedEntries<'a, T, B> {
966	type Item = IndexedEntryRef<'a, T, B>;
967
968	fn size_hint(&self) -> (usize, Option<usize>) {
969		let len = self.inner.len() + usize::from(self.index.is_some());
970		(len, Some(len))
971	}
972
973	fn next(&mut self) -> Option<Self::Item> {
974		self.index
975			.take()
976			.map(IndexedEntryRef::Index)
977			.or_else(|| self.inner.next().map(IndexedEntryRef::Node))
978	}
979}
980
981impl<'a, T, B> ExactSizeIterator for IndexedEntries<'a, T, B> {}
982
983#[derive(Educe, PartialEq, Eq)]
984#[educe(Clone, Copy)]
985pub enum IndexedEntryKeyRef<'a, T, B> {
986	Index,
987	Node(EntryKeyRef<'a, T, B>),
988}
989
990impl<'a, T, B> IndexedEntryKeyRef<'a, T, B> {
991	pub fn into_keyword(self) -> Option<Keyword> {
992		match self {
993			Self::Index => Some(Keyword::Index),
994			Self::Node(e) => e.into_keyword(),
995		}
996	}
997
998	pub fn as_keyword(&self) -> Option<Keyword> {
999		self.into_keyword()
1000	}
1001
1002	pub fn into_str(self) -> &'a str
1003	where
1004		T: AsRef<str>,
1005		B: AsRef<str>,
1006	{
1007		match self {
1008			Self::Index => "@index",
1009			Self::Node(e) => e.into_str(),
1010		}
1011	}
1012
1013	pub fn as_str(&self) -> &'a str
1014	where
1015		T: AsRef<str>,
1016		B: AsRef<str>,
1017	{
1018		self.into_str()
1019	}
1020}
1021
1022impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> IntoRefWithContext<'a, str, N>
1023	for IndexedEntryKeyRef<'a, T, B>
1024{
1025	fn into_ref_with(self, vocabulary: &'a N) -> &'a str {
1026		match self {
1027			IndexedEntryKeyRef::Index => "@index",
1028			IndexedEntryKeyRef::Node(e) => e.into_with(vocabulary).into_str(),
1029		}
1030	}
1031}
1032
1033#[derive(Educe)]
1034#[educe(Clone, Copy)]
1035pub enum IndexedEntryValueRef<'a, T, B> {
1036	Index(&'a str),
1037	Node(EntryValueRef<'a, T, B>),
1038}
1039
1040#[derive(Educe)]
1041#[educe(Clone, Copy)]
1042pub enum IndexedEntryRef<'a, T, B> {
1043	Index(&'a str),
1044	Node(EntryRef<'a, T, B>),
1045}
1046
1047impl<'a, T, B> IndexedEntryRef<'a, T, B> {
1048	pub fn into_key(self) -> IndexedEntryKeyRef<'a, T, B> {
1049		match self {
1050			Self::Index(_) => IndexedEntryKeyRef::Index,
1051			Self::Node(e) => IndexedEntryKeyRef::Node(e.key()),
1052		}
1053	}
1054
1055	pub fn key(&self) -> IndexedEntryKeyRef<'a, T, B> {
1056		self.into_key()
1057	}
1058
1059	pub fn into_value(self) -> IndexedEntryValueRef<'a, T, B> {
1060		match self {
1061			Self::Index(v) => IndexedEntryValueRef::Index(v),
1062			Self::Node(e) => IndexedEntryValueRef::Node(e.value()),
1063		}
1064	}
1065
1066	pub fn value(&self) -> IndexedEntryValueRef<'a, T, B> {
1067		self.into_value()
1068	}
1069
1070	pub fn into_key_value(self) -> (IndexedEntryKeyRef<'a, T, B>, IndexedEntryValueRef<'a, T, B>) {
1071		match self {
1072			Self::Index(v) => (IndexedEntryKeyRef::Index, IndexedEntryValueRef::Index(v)),
1073			Self::Node(e) => {
1074				let (k, v) = e.into_key_value();
1075				(IndexedEntryKeyRef::Node(k), IndexedEntryValueRef::Node(v))
1076			}
1077		}
1078	}
1079
1080	pub fn as_key_value(&self) -> (IndexedEntryKeyRef<'a, T, B>, IndexedEntryValueRef<'a, T, B>) {
1081		self.into_key_value()
1082	}
1083}
1084
1085/// Node object fragment reference.
1086pub enum FragmentRef<'a, T, B> {
1087	/// Node object entry.
1088	Entry(EntryRef<'a, T, B>),
1089
1090	/// Node object entry key.
1091	Key(EntryKeyRef<'a, T, B>),
1092
1093	/// Node object entry value.
1094	Value(EntryValueRef<'a, T, B>),
1095
1096	/// "@type" entry value fragment.
1097	TypeFragment(&'a Id<T, B>),
1098}
1099
1100impl<'a, T, B> FragmentRef<'a, T, B> {
1101	pub fn into_id(self) -> Option<&'a Id<T, B>> {
1102		match self {
1103			Self::Key(EntryKeyRef::Property(id)) => Some(id),
1104			Self::Value(EntryValueRef::Id(id)) => Some(id),
1105			Self::TypeFragment(ty) => Some(ty),
1106			_ => None,
1107		}
1108	}
1109
1110	pub fn as_id(&self) -> Option<&'a Id<T, B>> {
1111		match self {
1112			Self::Key(EntryKeyRef::Property(id)) => Some(id),
1113			Self::Value(EntryValueRef::Id(id)) => Some(id),
1114			Self::TypeFragment(ty) => Some(ty),
1115			_ => None,
1116		}
1117	}
1118
1119	pub fn is_json_array(&self) -> bool {
1120		match self {
1121			Self::Value(v) => v.is_json_array(),
1122			_ => false,
1123		}
1124	}
1125
1126	pub fn is_json_object(&self) -> bool {
1127		match self {
1128			Self::Value(v) => v.is_json_object(),
1129			_ => false,
1130		}
1131	}
1132
1133	pub fn sub_fragments(&self) -> SubFragments<'a, T, B> {
1134		match self {
1135			Self::Entry(e) => SubFragments::Entry(Some(e.key()), Some(e.value())),
1136			Self::Value(v) => v.sub_fragments(),
1137			_ => SubFragments::None,
1138		}
1139	}
1140}
1141
1142pub enum SubFragments<'a, T, B> {
1143	None,
1144	Entry(
1145		Option<EntryKeyRef<'a, T, B>>,
1146		Option<EntryValueRef<'a, T, B>>,
1147	),
1148	Type(std::slice::Iter<'a, Id<T, B>>),
1149	Graph(indexmap::set::Iter<'a, IndexedObject<T, B>>),
1150	Included(indexmap::set::Iter<'a, IndexedNode<T, B>>),
1151	Reverse(reverse_properties::Iter<'a, T, B>),
1152	Property(std::slice::Iter<'a, IndexedObject<T, B>>),
1153}
1154
1155impl<'a, T, B> Iterator for SubFragments<'a, T, B> {
1156	type Item = super::FragmentRef<'a, T, B>;
1157
1158	fn next(&mut self) -> Option<Self::Item> {
1159		match self {
1160			Self::None => None,
1161			Self::Entry(k, v) => k
1162				.take()
1163				.map(|k| super::FragmentRef::NodeFragment(FragmentRef::Key(k)))
1164				.or_else(|| {
1165					v.take()
1166						.map(|v| super::FragmentRef::NodeFragment(FragmentRef::Value(v)))
1167				}),
1168			Self::Type(l) => l
1169				.next_back()
1170				.map(|t| super::FragmentRef::NodeFragment(FragmentRef::TypeFragment(t))),
1171			Self::Graph(g) => g.next().map(|o| super::FragmentRef::IndexedObject(o)),
1172			Self::Included(i) => i.next().map(|n| super::FragmentRef::IndexedNode(n)),
1173			Self::Reverse(r) => r
1174				.next()
1175				.map(|(_, n)| super::FragmentRef::IndexedNodeList(n)),
1176			Self::Property(o) => o.next().map(|o| super::FragmentRef::IndexedObject(o)),
1177		}
1178	}
1179}
1180
1181impl<T, B> object::Any<T, B> for Node<T, B> {
1182	#[inline(always)]
1183	fn as_ref(&self) -> object::Ref<T, B> {
1184		object::Ref::Node(self)
1185	}
1186}
1187
1188impl<T, B> TryFrom<Object<T, B>> for Node<T, B> {
1189	type Error = Object<T, B>;
1190
1191	#[inline(always)]
1192	fn try_from(obj: Object<T, B>) -> Result<Node<T, B>, Object<T, B>> {
1193		match obj {
1194			Object::Node(node) => Ok(*node),
1195			obj => Err(obj),
1196		}
1197	}
1198}
1199
1200impl<T: Hash, B: Hash> Hash for Node<T, B> {
1201	#[inline]
1202	fn hash<H: Hasher>(&self, h: &mut H) {
1203		self.id.hash(h);
1204		utils::hash_set_opt(self.types.as_ref(), h);
1205		utils::hash_set_opt(self.graph.as_ref(), h);
1206		utils::hash_set_opt(self.included.as_ref(), h);
1207		self.properties.hash(h);
1208		self.reverse_properties.hash(h)
1209	}
1210}
1211
1212/// Iterator through indexed nodes.
1213pub struct Nodes<'a, T, B>(Option<std::slice::Iter<'a, IndexedNode<T, B>>>);
1214
1215impl<'a, T, B> Nodes<'a, T, B> {
1216	#[inline(always)]
1217	pub(crate) fn new(inner: Option<std::slice::Iter<'a, IndexedNode<T, B>>>) -> Self {
1218		Self(inner)
1219	}
1220}
1221
1222impl<'a, T, B> Iterator for Nodes<'a, T, B> {
1223	type Item = &'a IndexedNode<T, B>;
1224
1225	#[inline(always)]
1226	fn next(&mut self) -> Option<&'a IndexedNode<T, B>> {
1227		match &mut self.0 {
1228			None => None,
1229			Some(it) => it.next(),
1230		}
1231	}
1232}
1233
1234impl<T: Eq + Hash, B: Eq + Hash> TryFromJsonObject<T, B> for Node<T, B> {
1235	fn try_from_json_object_in(
1236		vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>,
1237		mut object: json_syntax::Object,
1238	) -> Result<Self, InvalidExpandedJson> {
1239		let id = match object
1240			.remove_unique("@id")
1241			.map_err(InvalidExpandedJson::duplicate_key)?
1242		{
1243			Some(entry) => Some(Id::try_from_json_in(vocabulary, entry.value)?),
1244			None => None,
1245		};
1246
1247		let types = match object
1248			.remove_unique("@type")
1249			.map_err(InvalidExpandedJson::duplicate_key)?
1250		{
1251			Some(entry) => Some(Vec::try_from_json_in(vocabulary, entry.value)?),
1252			None => None,
1253		};
1254
1255		let graph = match object
1256			.remove_unique("@graph")
1257			.map_err(InvalidExpandedJson::duplicate_key)?
1258		{
1259			Some(entry) => Some(IndexSet::try_from_json_in(vocabulary, entry.value)?),
1260			None => None,
1261		};
1262
1263		let included = match object
1264			.remove_unique("@included")
1265			.map_err(InvalidExpandedJson::duplicate_key)?
1266		{
1267			Some(entry) => Some(IndexSet::try_from_json_in(vocabulary, entry.value)?),
1268			None => None,
1269		};
1270
1271		let reverse_properties = match object
1272			.remove_unique("@reverse")
1273			.map_err(InvalidExpandedJson::duplicate_key)?
1274		{
1275			Some(entry) => Some(ReverseProperties::try_from_json_in(
1276				vocabulary,
1277				entry.value,
1278			)?),
1279			None => None,
1280		};
1281
1282		let properties = Properties::try_from_json_object_in(vocabulary, object)?;
1283
1284		Ok(Self {
1285			id,
1286			types,
1287			graph,
1288			included,
1289			reverse_properties,
1290			properties,
1291		})
1292	}
1293}
1294
1295impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> IntoJsonWithContext<N> for Node<T, B> {
1296	fn into_json_with(self, vocabulary: &N) -> json_syntax::Value {
1297		let mut obj = json_syntax::Object::new();
1298
1299		if let Some(id) = self.id {
1300			obj.insert("@id".into(), id.into_with(vocabulary).into_json());
1301		}
1302
1303		if let Some(types) = self.types {
1304			if !types.is_empty() {
1305				// let value = if types.len() > 1 {
1306				// 	types.value.into_with(vocabulary).into_json()
1307				// } else {
1308				// 	types.value.0.into_iter().next().unwrap().into_with(vocabulary).into_json()
1309				// };
1310				let value = types.into_with(vocabulary).into_json();
1311
1312				obj.insert("@type".into(), value);
1313			}
1314		}
1315
1316		if let Some(graph) = self.graph {
1317			obj.insert("@graph".into(), graph.into_with(vocabulary).into_json());
1318		}
1319
1320		if let Some(included) = self.included {
1321			obj.insert(
1322				"@include".into(),
1323				included.into_with(vocabulary).into_json(),
1324			);
1325		}
1326
1327		if let Some(reverse_properties) = self.reverse_properties {
1328			obj.insert(
1329				"@reverse".into(),
1330				reverse_properties.into_with(vocabulary).into_json(),
1331			);
1332		}
1333
1334		for (prop, objects) in self.properties {
1335			obj.insert(
1336				prop.with(vocabulary).to_string().into(),
1337				objects.into_json_with(vocabulary),
1338			);
1339		}
1340
1341		obj.into()
1342	}
1343}