Skip to main content

jsonld_core/object/
mod.rs

1//! Nodes, lists and values.
2use crate::{HashMap, Id, IndexSet, Indexed, LenientLangTag, Relabel, ValidId};
3use contextual::{IntoRefWithContext, WithContext};
4use derive_where::derive_where;
5use iri_rs::IriBuf;
6use jsonld_syntax::{IntoJsonWithContext, Keyword};
7use jstrict::Number;
8use rdfx::{
9    BlankIdBuf,
10    LocalGenerator,
11    vocabulary::{Vocabulary, VocabularyMut},
12};
13use smallvec::SmallVec;
14use std::hash::Hash;
15
16/// List objects.
17pub mod list;
18mod mapped_eq;
19/// Node objects.
20pub mod node;
21mod typ;
22/// Value objects.
23pub mod value;
24
25pub use list::List;
26pub use mapped_eq::MappedEq;
27pub use node::{Graph, IndexedNode, Node, Nodes};
28pub use typ::{Type, TypeRef};
29pub use value::{Literal, Value};
30
31/// Abstract object.
32pub trait Any<T, B> {
33    /// Borrows the object as a value, node or list reference.
34    fn as_ref(&self) -> Ref<'_, T, B>;
35
36    #[inline]
37    /// Returns the identifier (`@id`) of the object, if it is a node object
38    /// with one.
39    fn id(&self) -> Option<&Id<T, B>> {
40        match self.as_ref() {
41            Ref::Node(n) => n.id.as_ref(),
42            _ => None,
43        }
44    }
45
46    #[inline]
47    /// Returns the language tag of this value, if it carries one.
48    fn language<'a>(&'a self) -> Option<&'a LenientLangTag>
49    where
50        T: 'a,
51        B: 'a,
52    {
53        match self.as_ref() {
54            Ref::Value(value) => value.language(),
55            _ => None,
56        }
57    }
58
59    #[inline]
60    /// Checks whether the object is a value object.
61    fn is_value(&self) -> bool {
62        matches!(self.as_ref(), Ref::Value(_))
63    }
64
65    #[inline]
66    /// Checks whether the object is a node object.
67    fn is_node(&self) -> bool {
68        matches!(self.as_ref(), Ref::Node(_))
69    }
70
71    #[inline]
72    /// Checks whether the object is a graph object (a node object with a
73    /// `@graph` entry).
74    fn is_graph(&self) -> bool {
75        match self.as_ref() {
76            Ref::Node(n) => n.is_graph(),
77            _ => false,
78        }
79    }
80
81    #[inline]
82    /// Checks whether the object is a list object.
83    fn is_list(&self) -> bool {
84        matches!(self.as_ref(), Ref::List(_))
85    }
86}
87
88/// Object reference.
89pub enum Ref<'a, T, B> {
90    /// Value object.
91    Value(&'a Value<T>),
92
93    /// Node object.
94    Node(&'a Node<T, B>),
95
96    /// List object.
97    List(&'a List<T, B>),
98}
99
100/// Indexed object.
101pub type IndexedObject<T, B = ()> = Indexed<Object<T, B>>;
102
103/// Object.
104///
105/// JSON-LD connects together multiple kinds of data objects.
106/// Objects may be nodes, values or lists of objects.
107///
108/// You can get an `Object` by expanding a JSON-LD document using the
109/// expansion algorithm or by converting an already expanded JSON document
110/// using [`TryFromJson`].
111#[allow(clippy::derived_hash_with_manual_eq)]
112#[derive(Debug, Clone, Hash)]
113#[derive_where(PartialEq; T: Eq + Hash, B: Eq + Hash)]
114pub enum Object<T = IriBuf, B = BlankIdBuf> {
115    /// Value object.
116    Value(Value<T>),
117
118    /// Node object.
119    Node(Box<Node<T, B>>),
120
121    /// List object.
122    List(List<T, B>),
123}
124
125impl<T: Eq + Hash, B: Eq + Hash> Eq for Object<T, B> {}
126
127impl<T, B> Object<T, B> {
128    /// Creates a `null` value object.
129    #[inline(always)]
130    #[must_use]
131    pub fn null() -> Self {
132        Self::Value(Value::null())
133    }
134
135    /// Creates a new node object from a node.
136    #[inline(always)]
137    pub fn node(n: Node<T, B>) -> Self {
138        Self::Node(Box::new(n))
139    }
140
141    /// Identifier of the object, if it is a node object.
142    #[inline(always)]
143    pub fn id(&self) -> Option<&Id<T, B>> {
144        match self {
145            Object::Node(n) => n.id.as_ref(),
146            _ => None,
147        }
148    }
149
150    /// Assigns an identifier to every node included in this object using the given `generator`.
151    ///
152    /// # Errors
153    ///
154    /// Returns an error when the generator runs out of identifiers.
155    pub fn identify_all_with<V: VocabularyMut<Iri = T, BlankId = B>, G: LocalGenerator>(
156        &mut self,
157        vocabulary: &mut V,
158        generator: &mut G,
159    ) -> Result<(), crate::id::GeneratedIdError>
160    where
161        T: Eq + Hash,
162        B: Eq + Hash,
163    {
164        match self {
165            Object::Node(n) => n.identify_all_with(vocabulary, generator)?,
166            Object::List(l) => {
167                for object in l {
168                    object.identify_all_with(vocabulary, generator)?;
169                }
170            }
171            Object::Value(_) => (),
172        }
173        Ok(())
174    }
175
176    /// Use the given `generator` to assign an identifier to all nodes that
177    /// don't have one.
178    ///
179    /// # Errors
180    ///
181    /// Returns an error when the generator runs out of identifiers.
182    pub fn identify_all<G: LocalGenerator>(&mut self, generator: &mut G) -> Result<(), crate::id::GeneratedIdError>
183    where
184        T: Eq + Hash,
185        B: Eq + Hash,
186        (): Vocabulary<Iri = T, BlankId = B>,
187    {
188        self.identify_all_with(&mut (), generator)
189    }
190
191    /// Puts every literal of the object into canonical form, using the given
192    /// `buffer` to render numbers.
193    pub fn canonicalize_with(&mut self, buffer: &mut ryu_js::Buffer) {
194        match self {
195            Self::List(l) => l.canonicalize_with(buffer),
196            Self::Node(n) => n.canonicalize_with(buffer),
197            Self::Value(v) => v.canonicalize_with(buffer),
198        }
199    }
200
201    /// Puts every literal of the object into canonical form.
202    pub fn canonicalize(&mut self) {
203        let mut buffer = ryu_js::Buffer::new();
204        self.canonicalize_with(&mut buffer);
205    }
206
207    /// Returns an iterator over the types of the object.
208    pub fn types(&self) -> Types<'_, T, B> {
209        match self {
210            Self::Value(value) => Types::Value(value.typ()),
211            Self::Node(node) => Types::Node(node.types().iter()),
212            Self::List(_) => Types::List,
213        }
214    }
215
216    /// Identifier of the object as an IRI.
217    ///
218    /// If the object is a node identified by an IRI, returns this IRI.
219    /// Returns `None` otherwise.
220    #[inline(always)]
221    pub fn as_iri(&self) -> Option<&T> {
222        match self {
223            Object::Node(node) => node.as_iri(),
224            _ => None,
225        }
226    }
227
228    /// Tests if the object is a value.
229    #[inline(always)]
230    pub fn is_value(&self) -> bool {
231        matches!(self, Object::Value(_))
232    }
233
234    /// Returns this object as a value, if it is one.
235    #[inline(always)]
236    pub fn as_value(&self) -> Option<&Value<T>> {
237        match self {
238            Self::Value(v) => Some(v),
239            _ => None,
240        }
241    }
242
243    /// Returns this object as a mutable value, if it is one.
244    #[inline(always)]
245    pub fn as_value_mut(&mut self) -> Option<&mut Value<T>> {
246        match self {
247            Self::Value(v) => Some(v),
248            _ => None,
249        }
250    }
251
252    /// Converts this object into a value, if it is one.
253    #[inline(always)]
254    pub fn into_value(self) -> Option<Value<T>> {
255        match self {
256            Self::Value(v) => Some(v),
257            _ => None,
258        }
259    }
260
261    /// Tests if the object is a node.
262    #[inline(always)]
263    pub fn is_node(&self) -> bool {
264        matches!(self, Object::Node(_))
265    }
266
267    /// Returns this object as a node, if it is one.
268    #[inline(always)]
269    pub fn as_node(&self) -> Option<&Node<T, B>> {
270        match self {
271            Self::Node(n) => Some(n),
272            _ => None,
273        }
274    }
275
276    /// Returns this object as a mutable node, if it is one.
277    #[inline(always)]
278    pub fn as_node_mut(&mut self) -> Option<&mut Node<T, B>> {
279        match self {
280            Self::Node(n) => Some(n),
281            _ => None,
282        }
283    }
284
285    /// Converts this object into a node, if it is one.
286    #[inline(always)]
287    pub fn into_node(self) -> Option<Node<T, B>> {
288        match self {
289            Self::Node(n) => Some(*n),
290            _ => None,
291        }
292    }
293
294    /// Tests if the object is a graph object (a node with a `@graph` field).
295    #[inline(always)]
296    pub fn is_graph(&self) -> bool {
297        match self {
298            Object::Node(n) => n.is_graph(),
299            _ => false,
300        }
301    }
302
303    /// Tests if the object is a list.
304    #[inline(always)]
305    pub fn is_list(&self) -> bool {
306        matches!(self, Object::List(_))
307    }
308
309    /// Returns this object as a list, if it is one.
310    #[inline(always)]
311    pub fn as_list(&self) -> Option<&List<T, B>> {
312        match self {
313            Self::List(l) => Some(l),
314            _ => None,
315        }
316    }
317
318    /// Returns this object as a mutable list, if it is one.
319    #[inline(always)]
320    pub fn as_list_mut(&mut self) -> Option<&mut List<T, B>> {
321        match self {
322            Self::List(l) => Some(l),
323            _ => None,
324        }
325    }
326
327    /// Converts this object into a list, if it is one.
328    #[inline(always)]
329    pub fn into_list(self) -> Option<List<T, B>> {
330        match self {
331            Self::List(l) => Some(l),
332            _ => None,
333        }
334    }
335
336    /// Returns the object as a string.
337    ///
338    /// If the object is a value holding a string, returns that string.
339    /// If the object is a node with an identifier, returns the identifier as
340    /// a string. Returns `None` otherwise.
341    #[inline(always)]
342    pub fn as_str(&self) -> Option<&str>
343    where
344        T: AsRef<str>,
345        B: AsRef<str>,
346    {
347        match self {
348            Object::Value(value) => value.as_str(),
349            Object::Node(node) => node.as_str(),
350            Object::List(_) => None,
351        }
352    }
353
354    /// Returns the object as a boolean, if it is a value holding one.
355    #[inline(always)]
356    pub fn as_bool(&self) -> Option<bool> {
357        match self {
358            Object::Value(value) => value.as_bool(),
359            _ => None,
360        }
361    }
362
363    /// Returns the object as a number, if it is a value holding one.
364    #[inline(always)]
365    pub fn as_number(&self) -> Option<&Number> {
366        match self {
367            Object::Value(value) => value.as_number(),
368            _ => None,
369        }
370    }
371
372    /// Returns the associated language, if the object is a language-tagged
373    /// value.
374    #[inline(always)]
375    pub fn language(&self) -> Option<&LenientLangTag> {
376        match self {
377            Object::Value(value) => value.language(),
378            _ => None,
379        }
380    }
381
382    /// Returns an iterator over all fragments of this object, including the
383    /// object itself.
384    ///
385    /// Fragments include:
386    ///   - objects
387    ///   - key-value pairs,
388    ///   - keys
389    ///   - values
390    pub fn traverse(&self) -> Traverse<'_, T, B> {
391        Traverse::new(Some(FragmentRef::Object(self)))
392    }
393
394    fn sub_fragments(&self) -> ObjectSubFragments<'_, T, B> {
395        match self {
396            Self::Value(v) => ObjectSubFragments::Value(v.entries()),
397            Self::List(l) => ObjectSubFragments::List(Some(l.entry())),
398            Self::Node(n) => ObjectSubFragments::Node(n.entries()),
399        }
400    }
401
402    /// Equivalence operator.
403    ///
404    /// Equivalence differs from equality for anonymous objects: list objects
405    /// and anonymous node objects stand for implicit, unlabeled blank nodes,
406    /// so they are never equivalent to anything.
407    pub fn equivalent(&self, other: &Self) -> bool
408    where
409        T: Eq + Hash,
410        B: Eq + Hash,
411    {
412        match (self, other) {
413            (Self::Value(a), Self::Value(b)) => a == b,
414            (Self::Node(a), Self::Node(b)) => a.equivalent(b),
415            _ => false,
416        }
417    }
418
419    /// Returns an iterator over the entries of the JSON representation of
420    /// the object.
421    pub fn entries(&self) -> Entries<'_, T, B> {
422        match self {
423            Self::Value(value) => Entries::Value(value.entries()),
424            Self::List(list) => Entries::List(Some(list.entry())),
425            Self::Node(node) => Entries::Node(node.entries()),
426        }
427    }
428
429    /// Rewrites every IRI and identifier of the object (recursively) with
430    /// the given functions.
431    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>) -> Object<U, C>
432    where
433        U: Eq + Hash,
434        C: Eq + Hash,
435    {
436        self.map_ids_with(&mut map_iri, &mut map_id)
437    }
438
439    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>) -> Object<U, C>
440    where
441        U: Eq + Hash,
442        C: Eq + Hash,
443    {
444        match self {
445            Self::Value(value) => Object::Value(value.map_ids(map_iri)),
446            Self::List(list) => Object::List(list.map_ids_with(map_iri, map_id)),
447            Self::Node(node) => Object::Node(Box::new((*node).map_ids_with(map_iri, map_id))),
448        }
449    }
450}
451
452impl<T, B> Relabel<T, B> for Object<T, B> {
453    fn relabel_with<N: VocabularyMut<Iri = T, BlankId = B>, G: LocalGenerator>(
454        &mut self,
455        vocabulary: &mut N,
456        generator: &mut G,
457        relabeling: &mut HashMap<B, ValidId<T, B>>,
458    ) -> Result<(), crate::id::GeneratedIdError>
459    where
460        T: Clone + Eq + Hash,
461        B: Clone + Eq + Hash,
462    {
463        match self {
464            Self::Node(n) => n.relabel_with(vocabulary, generator, relabeling),
465            Self::List(l) => l.relabel_with(vocabulary, generator, relabeling),
466            Self::Value(_) => Ok(()),
467        }
468    }
469}
470
471impl<T: Eq + Hash, B: Eq + Hash> Indexed<Object<T, B>> {
472    /// Checks whether the two indexed objects are equivalent: same `@index`
473    /// and [equivalent](Object::equivalent) inner objects.
474    pub fn equivalent(&self, other: &Self) -> bool {
475        self.index() == other.index() && self.inner().equivalent(other.inner())
476    }
477}
478
479impl<T, B> Indexed<Object<T, B>> {
480    /// Converts this indexed object into an indexed node, if it is one.
481    #[inline(always)]
482    pub fn into_indexed_node(self) -> Option<Indexed<Node<T, B>>> {
483        let (object, index) = self.into_parts();
484        object.into_node().map(|node| Indexed::new(node, index))
485    }
486
487    /// Converts this indexed object into an indexed value, if it is one.
488    #[inline(always)]
489    pub fn into_indexed_value(self) -> Option<Indexed<Value<T>>> {
490        let (object, index) = self.into_parts();
491        object.into_value().map(|value| Indexed::new(value, index))
492    }
493
494    /// Converts this indexed object into an indexed list, if it is one.
495    #[inline(always)]
496    pub fn into_indexed_list(self) -> Option<Indexed<List<T, B>>> {
497        let (object, index) = self.into_parts();
498        object.into_list().map(|list| Indexed::new(list, index))
499    }
500
501    /// Try to convert this object into an unnamed graph.
502    ///
503    /// # Errors
504    ///
505    /// Returns `self` unchanged when the object is not a graph object, or is a named graph.
506    pub fn into_unnamed_graph(self) -> Result<Graph<T, B>, Self> {
507        let (obj, index) = self.into_parts();
508        match obj {
509            Object::Node(n) => match n.into_unnamed_graph() {
510                Ok(g) => Ok(g),
511                Err(n) => Err(Indexed::new(Object::Node(n), index)),
512            },
513            obj => Err(Indexed::new(obj, index)),
514        }
515    }
516
517    /// Returns an iterator over the entries of the JSON representation of
518    /// the object, including its `@index` entry if any.
519    pub fn entries(&self) -> IndexedEntries<'_, T, B> {
520        IndexedEntries {
521            index: self.index(),
522            inner: self.inner().entries(),
523        }
524    }
525}
526
527#[derive_where(Clone)]
528/// Iterator over the entries of an object.
529pub enum Entries<'a, T, B> {
530    /// A value object.
531    Value(value::Entries<'a, T>),
532    /// A list object.
533    List(Option<&'a [IndexedObject<T, B>]>),
534    /// A node object.
535    Node(node::Entries<'a, T, B>),
536}
537
538impl<'a, T, B> Iterator for Entries<'a, T, B> {
539    type Item = EntryRef<'a, T, B>;
540
541    fn size_hint(&self) -> (usize, Option<usize>) {
542        let len = match self {
543            Self::Value(v) => v.len(),
544            Self::List(l) => usize::from(l.is_some()),
545            Self::Node(n) => n.len(),
546        };
547
548        (len, Some(len))
549    }
550
551    fn next(&mut self) -> Option<Self::Item> {
552        match self {
553            Self::Value(v) => v.next().map(EntryRef::Value),
554            Self::List(l) => l.take().map(EntryRef::List),
555            Self::Node(n) => n.next().map(EntryRef::Node),
556        }
557    }
558}
559
560impl<T, B> ExactSizeIterator for Entries<'_, T, B> {}
561
562#[derive_where(Clone)]
563/// Iterator over the entries of an indexed object, `@index` included.
564pub struct IndexedEntries<'a, T, B> {
565    index: Option<&'a str>,
566    inner: Entries<'a, T, B>,
567}
568
569impl<'a, T, B> Iterator for IndexedEntries<'a, T, B> {
570    type Item = IndexedEntryRef<'a, T, B>;
571
572    fn size_hint(&self) -> (usize, Option<usize>) {
573        let len = self.inner.len() + usize::from(self.index.is_some());
574        (len, Some(len))
575    }
576
577    fn next(&mut self) -> Option<Self::Item> {
578        self.index
579            .take()
580            .map(IndexedEntryRef::Index)
581            .or_else(|| self.inner.next().map(IndexedEntryRef::Object))
582    }
583}
584
585impl<T, B> ExactSizeIterator for IndexedEntries<'_, T, B> {}
586
587// `bound(false)`: every variant payload is a shared reference, a `Copy` value
588// type, or another unconditionally-`Copy` borrow type, so the impls hold for any
589// `T`/`B`. A plain `derive` would instead add a bound per field
590// type, making the impl conditional and breaking the `&self` methods that consume
591// `self` by copy.
592#[derive(PartialEq, Eq)]
593#[derive_where(Clone, Copy)]
594/// Key of an object entry.
595pub enum EntryKeyRef<'a, T, B> {
596    /// A value object.
597    Value(value::EntryKey),
598    /// A list object.
599    List,
600    /// A node object.
601    Node(node::EntryKeyRef<'a, T, B>),
602}
603
604impl<'a, T, B> EntryKeyRef<'a, T, B> {
605    /// Returns the JSON-LD keyword this key stands for, if any.
606    #[must_use]
607    pub fn into_keyword(self) -> Option<Keyword> {
608        match self {
609            Self::Value(e) => Some(e.into_keyword()),
610            Self::List => Some(Keyword::List),
611            Self::Node(e) => e.into_keyword(),
612        }
613    }
614
615    /// Returns the JSON-LD keyword this key stands for, if any.
616    #[must_use]
617    pub fn as_keyword(&self) -> Option<Keyword> {
618        self.into_keyword()
619    }
620
621    /// Returns the key as a string slice.
622    #[must_use]
623    pub fn into_str(self) -> &'a str
624    where
625        T: AsRef<str>,
626        B: AsRef<str>,
627    {
628        match self {
629            Self::Value(e) => e.into_str(),
630            Self::List => "@list",
631            Self::Node(e) => e.into_str(),
632        }
633    }
634
635    /// Returns this value as a string slice.
636    #[must_use]
637    pub fn as_str(self) -> &'a str
638    where
639        T: AsRef<str>,
640        B: AsRef<str>,
641    {
642        self.into_str()
643    }
644}
645
646impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> IntoRefWithContext<'a, str, N> for EntryKeyRef<'a, T, B> {
647    fn into_ref_with(self, vocabulary: &'a N) -> &'a str {
648        match self {
649            EntryKeyRef::Value(e) => e.into_str(),
650            EntryKeyRef::List => "@list",
651            EntryKeyRef::Node(e) => e.into_with(vocabulary).into_str(),
652        }
653    }
654}
655
656#[derive_where(Clone, Copy)]
657/// Value of an object entry.
658pub enum EntryValueRef<'a, T, B> {
659    /// A value object.
660    Value(value::EntryRef<'a, T>),
661    /// A list object.
662    List(&'a [IndexedObject<T, B>]),
663    /// A node object.
664    Node(node::EntryValueRef<'a, T, B>),
665}
666
667#[derive_where(Clone, Copy)]
668/// Entry of an object, key and value together.
669pub enum EntryRef<'a, T, B> {
670    /// A value object.
671    Value(value::EntryRef<'a, T>),
672    /// A list object.
673    List(&'a [IndexedObject<T, B>]),
674    /// A node object.
675    Node(node::EntryRef<'a, T, B>),
676}
677
678impl<'a, T, B> EntryRef<'a, T, B> {
679    /// Consumes this `EntryRef`, returning its key.
680    #[must_use]
681    pub fn into_key(self) -> EntryKeyRef<'a, T, B> {
682        match self {
683            Self::Value(e) => EntryKeyRef::Value(e.key()),
684            Self::List(_) => EntryKeyRef::List,
685            Self::Node(e) => EntryKeyRef::Node(e.key()),
686        }
687    }
688
689    /// Returns the key of this `EntryRef`.
690    #[must_use]
691    pub fn key(&self) -> EntryKeyRef<'a, T, B> {
692        self.into_key()
693    }
694
695    /// Consumes this `EntryRef`, returning its value.
696    #[must_use]
697    pub fn into_value(self) -> EntryValueRef<'a, T, B> {
698        match self {
699            Self::Value(v) => EntryValueRef::Value(v),
700            Self::List(v) => EntryValueRef::List(v),
701            Self::Node(e) => EntryValueRef::Node(e.value()),
702        }
703    }
704
705    /// Returns the value of this `EntryRef`.
706    #[must_use]
707    pub fn value(&self) -> EntryValueRef<'a, T, B> {
708        self.into_value()
709    }
710
711    /// Consumes this `EntryRef`, returning its key and value.
712    #[must_use]
713    pub fn into_key_value(self) -> (EntryKeyRef<'a, T, B>, EntryValueRef<'a, T, B>) {
714        match self {
715            Self::Value(e) => (EntryKeyRef::Value(e.key()), EntryValueRef::Value(e)),
716            Self::List(e) => (EntryKeyRef::List, EntryValueRef::List(e)),
717            Self::Node(e) => {
718                let (k, v) = e.into_key_value();
719                (EntryKeyRef::Node(k), EntryValueRef::Node(v))
720            }
721        }
722    }
723
724    /// Returns the key and value of this entry.
725    #[must_use]
726    pub fn as_key_value(&self) -> (EntryKeyRef<'a, T, B>, EntryValueRef<'a, T, B>) {
727        self.into_key_value()
728    }
729}
730
731#[derive(PartialEq, Eq)]
732#[derive_where(Clone, Copy)]
733/// Key of an indexed object entry.
734pub enum IndexedEntryKeyRef<'a, T, B> {
735    /// The `@index` entry.
736    Index,
737    /// The key of one of the object's own entries.
738    Object(EntryKeyRef<'a, T, B>),
739}
740
741impl<'a, T, B> IndexedEntryKeyRef<'a, T, B> {
742    /// Returns the JSON-LD keyword this key stands for, if any.
743    #[must_use]
744    pub fn into_keyword(self) -> Option<Keyword> {
745        match self {
746            Self::Index => Some(Keyword::Index),
747            Self::Object(e) => e.into_keyword(),
748        }
749    }
750
751    /// Returns the JSON-LD keyword this key stands for, if any.
752    #[must_use]
753    pub fn as_keyword(&self) -> Option<Keyword> {
754        self.into_keyword()
755    }
756
757    /// Returns the key as a string slice.
758    #[must_use]
759    pub fn into_str(self) -> &'a str
760    where
761        T: AsRef<str>,
762        B: AsRef<str>,
763    {
764        match self {
765            Self::Index => "@index",
766            Self::Object(e) => e.into_str(),
767        }
768    }
769
770    /// Returns this value as a string slice.
771    #[must_use]
772    pub fn as_str(&self) -> &'a str
773    where
774        T: AsRef<str>,
775        B: AsRef<str>,
776    {
777        self.into_str()
778    }
779}
780
781impl<'a, T, B, N: Vocabulary<Iri = T, BlankId = B>> IntoRefWithContext<'a, str, N> for IndexedEntryKeyRef<'a, T, B> {
782    fn into_ref_with(self, vocabulary: &'a N) -> &'a str {
783        match self {
784            IndexedEntryKeyRef::Index => "@index",
785            IndexedEntryKeyRef::Object(e) => e.into_with(vocabulary).into_str(),
786        }
787    }
788}
789
790#[derive_where(Clone, Copy)]
791/// Value of an indexed object entry.
792pub enum IndexedEntryValueRef<'a, T, B> {
793    /// The value of the `@index` entry.
794    Index(&'a str),
795    /// The value of one of the object's own entries.
796    Object(EntryValueRef<'a, T, B>),
797}
798
799#[derive_where(Clone, Copy)]
800/// Entry of an indexed object, key and value together.
801pub enum IndexedEntryRef<'a, T, B> {
802    /// The `@index` entry and its value.
803    Index(&'a str),
804    /// One of the object's own entries.
805    Object(EntryRef<'a, T, B>),
806}
807
808impl<'a, T, B> IndexedEntryRef<'a, T, B> {
809    /// Consumes this `IndexedEntryRef`, returning its key.
810    #[must_use]
811    pub fn into_key(self) -> IndexedEntryKeyRef<'a, T, B> {
812        match self {
813            Self::Index(_) => IndexedEntryKeyRef::Index,
814            Self::Object(e) => IndexedEntryKeyRef::Object(e.key()),
815        }
816    }
817
818    /// Returns the key of this `IndexedEntryRef`.
819    #[must_use]
820    pub fn key(&self) -> IndexedEntryKeyRef<'a, T, B> {
821        self.into_key()
822    }
823
824    /// Consumes this `IndexedEntryRef`, returning its value.
825    #[must_use]
826    pub fn into_value(self) -> IndexedEntryValueRef<'a, T, B> {
827        match self {
828            Self::Index(v) => IndexedEntryValueRef::Index(v),
829            Self::Object(e) => IndexedEntryValueRef::Object(e.value()),
830        }
831    }
832
833    /// Returns the value of this `IndexedEntryRef`.
834    #[must_use]
835    pub fn value(&self) -> IndexedEntryValueRef<'a, T, B> {
836        self.into_value()
837    }
838
839    /// Consumes this `IndexedEntryRef`, returning its key and value.
840    #[must_use]
841    pub fn into_key_value(self) -> (IndexedEntryKeyRef<'a, T, B>, IndexedEntryValueRef<'a, T, B>) {
842        match self {
843            Self::Index(v) => (IndexedEntryKeyRef::Index, IndexedEntryValueRef::Index(v)),
844            Self::Object(e) => {
845                let (k, v) = e.into_key_value();
846                (IndexedEntryKeyRef::Object(k), IndexedEntryValueRef::Object(v))
847            }
848        }
849    }
850
851    /// Returns the key and value of this entry.
852    #[must_use]
853    pub fn as_key_value(&self) -> (IndexedEntryKeyRef<'a, T, B>, IndexedEntryValueRef<'a, T, B>) {
854        self.into_key_value()
855    }
856}
857
858/// Try to convert from a JSON value directly into an expanded JSON-LD document
859/// without going through the expansion algorithm.
860///
861/// The input JSON value must be in expanded JSON-LD form.
862pub trait TryFromJson<T, B>: Sized {
863    /// Builds this fragment from a JSON value, interning terms in the given
864    /// vocabulary.
865    ///
866    /// # Errors
867    ///
868    /// Returns an error when the JSON does not describe a valid expanded object.
869    fn try_from_json_in(vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>, value: jstrict::Value) -> Result<Self, InvalidExpandedJson>;
870}
871
872/// Try to convert from a JSON object directly into an expanded JSON-LD object
873/// without going through the expansion algorithm.
874///
875/// The input JSON object must be in expanded JSON-LD form.
876pub trait TryFromJsonObject<T, B>: Sized {
877    /// Builds this fragment from a JSON object, interning terms in the given
878    /// vocabulary.
879    ///
880    /// # Errors
881    ///
882    /// Returns an error when the JSON object does not describe a valid expanded object.
883    fn try_from_json_object_in(vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>, object: jstrict::Object) -> Result<Self, InvalidExpandedJson>;
884}
885
886impl<T, B, V: TryFromJson<T, B>> TryFromJson<T, B> for Vec<V> {
887    fn try_from_json_in(vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>, value: jstrict::Value) -> Result<Self, InvalidExpandedJson> {
888        match value {
889            jstrict::Value::Array(items) => {
890                let mut result = Vec::new();
891
892                for item in items {
893                    result.push(V::try_from_json_in(vocabulary, item)?);
894                }
895
896                Ok(result)
897            }
898            _ => Err(InvalidExpandedJson::InvalidList),
899        }
900    }
901}
902
903impl<T, B, V: Eq + Hash + TryFromJson<T, B>> TryFromJson<T, B> for IndexSet<V> {
904    fn try_from_json_in(vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>, value: jstrict::Value) -> Result<Self, InvalidExpandedJson> {
905        match value {
906            jstrict::Value::Array(items) => {
907                let mut result = IndexSet::default();
908
909                for item in items {
910                    result.insert(V::try_from_json_in(vocabulary, item)?);
911                }
912
913                Ok(result)
914            }
915            _ => Err(InvalidExpandedJson::InvalidList),
916        }
917    }
918}
919
920impl<T: Eq + Hash, B: Eq + Hash> TryFromJson<T, B> for Object<T, B> {
921    fn try_from_json_in(vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>, value: jstrict::Value) -> Result<Self, InvalidExpandedJson> {
922        match value {
923            jstrict::Value::Object(object) => Self::try_from_json_object_in(vocabulary, object),
924            _ => Err(InvalidExpandedJson::InvalidObject),
925        }
926    }
927}
928
929impl<T: Eq + Hash, B: Eq + Hash> TryFromJsonObject<T, B> for Object<T, B> {
930    fn try_from_json_object_in(vocabulary: &mut impl VocabularyMut<Iri = T, BlankId = B>, mut object: jstrict::Object) -> Result<Self, InvalidExpandedJson> {
931        match object.remove_unique("@context").map_err(InvalidExpandedJson::duplicate_key)? {
932            Some(_) => Err(InvalidExpandedJson::NotExpanded),
933            None => {
934                if let Some(value_entry) = object.remove_unique("@value").map_err(InvalidExpandedJson::duplicate_key)? {
935                    Ok(Self::Value(Value::try_from_json_object_in(vocabulary, object, value_entry)?))
936                } else if let Some(list_entry) = object.remove_unique("@list").map_err(InvalidExpandedJson::duplicate_key)? {
937                    Ok(Self::List(List::try_from_json_object_in(vocabulary, object, list_entry)?))
938                } else {
939                    let node = Node::try_from_json_object_in(vocabulary, object)?;
940                    Ok(Self::node(node))
941                }
942            }
943        }
944    }
945}
946
947/// Invalid expanded JSON object error.
948///
949/// This can be raised when trying to directly convert a JSON value into an
950/// expanded JSON-LD object without using the expansion algorithm.
951#[derive(Debug, thiserror::Error)]
952pub enum InvalidExpandedJson {
953    /// The value is not a JSON object.
954    #[error("invalid object")]
955    InvalidObject,
956    /// The `@list` entry does not hold an array.
957    #[error("invalid `@list` value")]
958    InvalidList,
959    /// The `@index` entry does not hold a string.
960    #[error("invalid `@index` value")]
961    InvalidIndex,
962    /// The `@id` entry does not hold a valid identifier.
963    #[error("invalid `@id` value")]
964    InvalidId,
965    /// The `@type` entry of a value object is invalid.
966    #[error("invalid `@type` value")]
967    InvalidValueType,
968    /// The `@value` entry does not hold a literal.
969    #[error("invalid literal")]
970    InvalidLiteral,
971    /// The `@language` entry does not hold a language tag.
972    #[error("invalid `@language` value")]
973    InvalidLanguage,
974    /// The `@direction` entry does not hold `ltr` or `rtl`.
975    #[error("invalid `@direction` value")]
976    InvalidDirection,
977    /// The value is not a well-formed language-tagged string.
978    #[error("invalid language-tagged string")]
979    InvalidLangString,
980    /// The document is not in expanded form.
981    #[error("not an expanded document")]
982    NotExpanded,
983    /// The object carries an entry that is not allowed here.
984    #[error("unexpected entry")]
985    UnexpectedEntry,
986    /// The object carries the same key twice.
987    #[error("duplicate key `{0}`")]
988    DuplicateKey(jstrict::object::Key),
989    /// A value of the wrong JSON kind was found.
990    #[error("unexpected {0}, expected {1}")]
991    Unexpected(jstrict::Kind, jstrict::Kind),
992}
993
994impl InvalidExpandedJson {
995    /// Builds a duplicate-key error from the duplicate `jstrict` reports.
996    #[must_use]
997    pub fn duplicate_key(jstrict::object::Duplicate(a, _): jstrict::object::Duplicate<jstrict::object::Entry>) -> Self {
998        InvalidExpandedJson::DuplicateKey(a.key)
999    }
1000}
1001
1002impl<T, B> Any<T, B> for Object<T, B> {
1003    #[inline(always)]
1004    fn as_ref(&self) -> Ref<'_, T, B> {
1005        match self {
1006            Object::Value(value) => Ref::Value(value),
1007            Object::Node(node) => Ref::Node(node),
1008            Object::List(list) => Ref::List(list),
1009        }
1010    }
1011}
1012
1013impl<T, B> From<Value<T>> for Object<T, B> {
1014    #[inline(always)]
1015    fn from(value: Value<T>) -> Self {
1016        Self::Value(value)
1017    }
1018}
1019
1020impl<T, B> From<Node<T, B>> for Object<T, B> {
1021    #[inline(always)]
1022    fn from(node: Node<T, B>) -> Self {
1023        Self::node(node)
1024    }
1025}
1026
1027/// Iterator through the types of an object.
1028pub enum Types<'a, T, B> {
1029    /// A value object.
1030    Value(Option<value::TypeRef<'a, T>>),
1031    /// A node object.
1032    Node(std::slice::Iter<'a, Id<T, B>>),
1033    /// A list object.
1034    List,
1035}
1036
1037impl<'a, T, B> Iterator for Types<'a, T, B> {
1038    type Item = TypeRef<'a, T, B>;
1039
1040    fn next(&mut self) -> Option<Self::Item> {
1041        match self {
1042            Self::Value(ty) => ty.take().map(TypeRef::from_value_type),
1043            Self::Node(tys) => tys.next().map(TypeRef::from_reference),
1044            Self::List => None,
1045        }
1046    }
1047}
1048
1049/// Iterator through indexed objects.
1050pub struct Objects<'a, T, B>(Option<std::slice::Iter<'a, IndexedObject<T, B>>>);
1051
1052impl<'a, T, B> Objects<'a, T, B> {
1053    #[inline(always)]
1054    pub(crate) fn new(inner: Option<std::slice::Iter<'a, IndexedObject<T, B>>>) -> Self {
1055        Self(inner)
1056    }
1057}
1058
1059impl<'a, T, B> Iterator for Objects<'a, T, B> {
1060    type Item = &'a IndexedObject<T, B>;
1061
1062    #[inline(always)]
1063    fn next(&mut self) -> Option<&'a IndexedObject<T, B>> {
1064        match &mut self.0 {
1065            None => None,
1066            Some(it) => it.next(),
1067        }
1068    }
1069}
1070
1071/// Object fragment.
1072pub enum FragmentRef<'a, T, B> {
1073    /// "@index" entry.
1074    IndexEntry(&'a str),
1075
1076    /// "@index" entry key.
1077    IndexKey,
1078
1079    /// "@index" entry value.
1080    IndexValue(&'a str),
1081
1082    /// Object.
1083    Object(&'a Object<T, B>),
1084
1085    /// Indexed object.
1086    IndexedObject(&'a Indexed<Object<T, B>>),
1087
1088    /// Node object.
1089    Node(&'a Node<T, B>),
1090
1091    /// Indexed node object.
1092    IndexedNode(&'a IndexedNode<T, B>),
1093
1094    /// Indexed node list.
1095    IndexedNodeList(&'a [IndexedNode<T, B>]),
1096
1097    /// Value object fragment.
1098    ValueFragment(value::FragmentRef<'a, T>),
1099
1100    /// List object fragment.
1101    ListFragment(list::FragmentRef<'a, T, B>),
1102
1103    /// Node object fragment.
1104    NodeFragment(node::FragmentRef<'a, T, B>),
1105}
1106
1107impl<'a, T, B> FragmentRef<'a, T, B> {
1108    /// Returns the object this fragment stands for, if it is one.
1109    #[must_use]
1110    pub fn into_ref(self) -> Option<Ref<'a, T, B>> {
1111        match self {
1112            Self::Object(o) => Some(o.as_ref()),
1113            Self::IndexedObject(o) => Some(o.inner().as_ref()),
1114            Self::Node(n) => Some(n.as_ref()),
1115            Self::IndexedNode(n) => Some(n.inner().as_ref()),
1116            _ => None,
1117        }
1118    }
1119
1120    /// Returns the identifier this fragment stands for, if it is one.
1121    pub fn into_id(self) -> Option<Id<&'a T, &'a B>> {
1122        match self {
1123            Self::ValueFragment(i) => i.into_iri().map(Id::iri),
1124            Self::NodeFragment(i) => i.into_id().map(Into::into),
1125            _ => None,
1126        }
1127    }
1128
1129    /// Returns the identifier this fragment stands for, if it is one.
1130    pub fn as_id(&self) -> Option<Id<&'a T, &'a B>> {
1131        match self {
1132            Self::ValueFragment(i) => i.as_iri().map(Id::iri),
1133            Self::NodeFragment(i) => i.as_id().map(Into::into),
1134            _ => None,
1135        }
1136    }
1137
1138    /// Checks whether this fragment renders as a JSON array.
1139    #[must_use]
1140    pub fn is_json_array(&self) -> bool {
1141        match self {
1142            Self::IndexedNodeList(_) => true,
1143            Self::ValueFragment(i) => i.is_json_array(),
1144            Self::NodeFragment(n) => n.is_json_array(),
1145            _ => false,
1146        }
1147    }
1148
1149    /// Checks whether this fragment renders as a JSON object.
1150    #[must_use]
1151    pub fn is_json_object(&self) -> bool {
1152        match self {
1153            Self::Object(_) | Self::IndexedObject(_) | Self::Node(_) | Self::IndexedNode(_) => true,
1154            Self::ValueFragment(i) => i.is_json_object(),
1155            Self::NodeFragment(i) => i.is_json_object(),
1156            _ => false,
1157        }
1158    }
1159
1160    /// Returns an iterator over the fragments directly contained in this one.
1161    #[must_use]
1162    pub fn sub_fragments(&self) -> SubFragments<'a, T, B> {
1163        match self {
1164            Self::IndexEntry(v) => SubFragments::IndexEntry(Some(()), Some(v)),
1165            Self::Object(o) => SubFragments::Object(None, o.sub_fragments()),
1166            Self::IndexedObject(o) => SubFragments::Object(o.index(), o.sub_fragments()),
1167            Self::Node(n) => SubFragments::Object(None, ObjectSubFragments::Node(n.entries())),
1168            Self::IndexedNode(n) => SubFragments::Object(n.index(), ObjectSubFragments::Node(n.inner().entries())),
1169            Self::IndexedNodeList(l) => SubFragments::IndexedNodeList(l.iter()),
1170            Self::ValueFragment(i) => SubFragments::Value(i.sub_fragments()),
1171            Self::NodeFragment(i) => SubFragments::Node(i.sub_fragments()),
1172            Self::ListFragment(l) => SubFragments::List(l.sub_fragments()),
1173            Self::IndexKey | Self::IndexValue(_) => SubFragments::None,
1174        }
1175    }
1176}
1177
1178/// Iterator over the fragments directly held by an object.
1179pub enum ObjectSubFragments<'a, T, B> {
1180    /// A list object.
1181    List(Option<&'a [IndexedObject<T, B>]>),
1182    /// A value object.
1183    Value(value::Entries<'a, T>),
1184    /// A node object.
1185    Node(node::Entries<'a, T, B>),
1186}
1187
1188impl<'a, T, B> Iterator for ObjectSubFragments<'a, T, B> {
1189    type Item = FragmentRef<'a, T, B>;
1190
1191    fn next(&mut self) -> Option<Self::Item> {
1192        match self {
1193            Self::List(l) => l.take().map(|e| FragmentRef::ListFragment(list::FragmentRef::Entry(e))),
1194            Self::Value(e) => e.next_back().map(|e| FragmentRef::ValueFragment(value::FragmentRef::Entry(e))),
1195            Self::Node(e) => e.next().map(|e| FragmentRef::NodeFragment(node::FragmentRef::Entry(e))),
1196        }
1197    }
1198}
1199
1200/// Iterator over the fragments directly held by a document fragment.
1201pub enum SubFragments<'a, T, B> {
1202    /// No value.
1203    None,
1204    /// The `@index` entry of an indexed fragment.
1205    IndexEntry(Option<()>, Option<&'a str>),
1206    /// A JSON object.
1207    Object(Option<&'a str>, ObjectSubFragments<'a, T, B>),
1208    /// A value object.
1209    Value(value::SubFragments<'a, T>),
1210    /// A node object.
1211    Node(node::SubFragments<'a, T, B>),
1212    /// A list object.
1213    List(list::SubFragments<'a, T, B>),
1214    /// A list of indexed node objects.
1215    IndexedNodeList(std::slice::Iter<'a, IndexedNode<T, B>>),
1216}
1217
1218impl<'a, T, B> Iterator for SubFragments<'a, T, B> {
1219    type Item = FragmentRef<'a, T, B>;
1220
1221    fn next(&mut self) -> Option<Self::Item> {
1222        match self {
1223            Self::None => None,
1224            Self::IndexEntry(k, v) => k.take().map(|()| FragmentRef::IndexKey).or_else(|| v.take().map(FragmentRef::IndexValue)),
1225            Self::Object(index, i) => match index.take() {
1226                Some(index) => Some(FragmentRef::IndexEntry(index)),
1227                None => i.next(),
1228            },
1229            Self::Value(i) => i.next().map(FragmentRef::ValueFragment),
1230            Self::Node(i) => i.next(),
1231            Self::List(i) => i.next(),
1232            Self::IndexedNodeList(i) => i.next().map(FragmentRef::IndexedNode),
1233        }
1234    }
1235}
1236
1237/// Depth-first iterator over a fragment and everything it contains.
1238pub struct Traverse<'a, T, B> {
1239    stack: SmallVec<[FragmentRef<'a, T, B>; 8]>,
1240}
1241
1242impl<'a, T, B> Traverse<'a, T, B> {
1243    pub(crate) fn new(items: impl IntoIterator<Item = FragmentRef<'a, T, B>>) -> Self {
1244        let stack = items.into_iter().collect();
1245        Self { stack }
1246    }
1247}
1248
1249impl<'a, T, B> Iterator for Traverse<'a, T, B> {
1250    type Item = FragmentRef<'a, T, B>;
1251
1252    fn next(&mut self) -> Option<Self::Item> {
1253        match self.stack.pop() {
1254            Some(item) => {
1255                self.stack.extend(item.sub_fragments());
1256                Some(item)
1257            }
1258            None => None,
1259        }
1260    }
1261}
1262
1263impl<T, B, N: Vocabulary<Iri = T, BlankId = B>> IntoJsonWithContext<N> for Object<T, B> {
1264    fn into_json_with(self, vocabulary: &N) -> jstrict::Value {
1265        match self {
1266            Self::Value(v) => v.into_json_with(vocabulary),
1267            Self::Node(n) => n.into_json_with(vocabulary),
1268            Self::List(l) => l.into_json_with(vocabulary),
1269        }
1270    }
1271}