Skip to main content

jsonld_core/object/node/
mod.rs

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