Skip to main content

jsonld_syntax/context/definition/
reference.rs

1use super::{BindingsIter, Definition, EntryValueSubItems, Key, Type, Version, Vocab};
2use crate::{Direction, LenientLangTagBuf, Nullable, context::TermDefinition};
3
4use iri_rs::IriRefBuf;
5
6impl Definition {
7    /// Returns an iterator over the entries of this context definition.
8    ///
9    /// The keyword entries come first, in the order they are declared on
10    /// [`Definition`], followed by the term bindings in insertion order.
11    pub fn iter(&self) -> Entries<'_> {
12        Entries {
13            base: self.base.as_ref().map(Nullable::as_ref),
14            import: self.import.as_ref(),
15            language: self.language.as_ref().map(Nullable::as_ref),
16            direction: self.direction,
17            propagate: self.propagate,
18            protected: self.protected,
19            type_: self.type_,
20            version: self.version,
21            vocab: self.vocab.as_ref().map(Nullable::as_ref),
22            bindings: self.bindings.iter(),
23        }
24    }
25}
26
27/// Iterator over the entries of a context definition.
28pub struct Entries<'a> {
29    base: Option<Nullable<&'a IriRefBuf>>,
30    import: Option<&'a IriRefBuf>,
31    language: Option<Nullable<&'a LenientLangTagBuf>>,
32    direction: Option<Nullable<Direction>>,
33    propagate: Option<bool>,
34    protected: Option<bool>,
35    type_: Option<Type>,
36    version: Option<Version>,
37    vocab: Option<Nullable<&'a Vocab>>,
38    bindings: BindingsIter<'a>,
39}
40
41impl<'a> Iterator for Entries<'a> {
42    type Item = EntryRef<'a>;
43
44    fn size_hint(&self) -> (usize, Option<usize>) {
45        let mut len = self.bindings.len();
46
47        if self.base.is_some() {
48            len += 1;
49        }
50
51        if self.import.is_some() {
52            len += 1;
53        }
54
55        if self.language.is_some() {
56            len += 1;
57        }
58
59        if self.direction.is_some() {
60            len += 1;
61        }
62
63        if self.propagate.is_some() {
64            len += 1;
65        }
66
67        if self.protected.is_some() {
68            len += 1;
69        }
70
71        if self.type_.is_some() {
72            len += 1;
73        }
74
75        if self.version.is_some() {
76            len += 1;
77        }
78
79        if self.vocab.is_some() {
80            len += 1;
81        }
82
83        (len, Some(len))
84    }
85
86    fn next(&mut self) -> Option<Self::Item> {
87        match self.base.take() {
88            Some(value) => Some(EntryRef::Base(value)),
89            None => match self.import.take() {
90                Some(value) => Some(EntryRef::Import(value)),
91                None => match self.language.take() {
92                    Some(value) => Some(EntryRef::Language(value)),
93                    None => match self.direction.take() {
94                        Some(value) => Some(EntryRef::Direction(value)),
95                        None => match self.propagate.take() {
96                            Some(value) => Some(EntryRef::Propagate(value)),
97                            None => match self.protected.take() {
98                                Some(value) => Some(EntryRef::Protected(value)),
99                                None => match self.type_.take() {
100                                    Some(value) => Some(EntryRef::Type(value)),
101                                    None => match self.version.take() {
102                                        Some(value) => Some(EntryRef::Version(value)),
103                                        None => match self.vocab.take() {
104                                            Some(value) => Some(EntryRef::Vocab(value)),
105                                            None => self.bindings.next().map(|(k, v)| EntryRef::Definition(k, v)),
106                                        },
107                                    },
108                                },
109                            },
110                        },
111                    },
112                },
113            },
114        }
115    }
116}
117
118impl ExactSizeIterator for Entries<'_> {}
119
120/// Value of a context definition entry.
121pub enum EntryValueRef<'a> {
122    /// The `@base` entry, setting the base IRI against which relative IRIs are resolved.
123    Base(Nullable<&'a IriRefBuf>),
124    /// The `@import` entry, referencing a context to merge into this one.
125    Import(&'a IriRefBuf),
126    /// The `@language` entry, tagging string values with a language.
127    Language(Nullable<&'a LenientLangTagBuf>),
128    /// The `@direction` entry, setting the base direction of string values.
129    Direction(Nullable<Direction>),
130    /// The `@propagate` entry, controlling whether the context survives into node objects.
131    Propagate(bool),
132    /// The `@protected` entry, forbidding redefinition of the terms defined here.
133    Protected(bool),
134    /// The `@type` entry, setting how the node types of the described documents
135    /// are laid out and whether that setting is protected.
136    Type(Type),
137    /// The `@version` entry, declaring the processing mode.
138    Version(Version),
139    /// The `@vocab` entry, setting the vocabulary against which terms expand.
140    Vocab(Nullable<&'a Vocab>),
141    /// The definition bound to a term, or `null` to unset that term.
142    Definition(Nullable<&'a TermDefinition>),
143}
144
145impl<'a> EntryValueRef<'a> {
146    /// Checks whether this value is a JSON object: the `@type` entry, or an
147    /// expanded term definition.
148    #[must_use]
149    pub fn is_object(&self) -> bool {
150        match self {
151            Self::Type(_) => true,
152            Self::Definition(Nullable::Some(d)) => d.is_object(),
153            _ => false,
154        }
155    }
156
157    /// Returns an iterator over the fragments held by this value.
158    #[must_use]
159    pub fn sub_items(&self) -> EntryValueSubItems<'a> {
160        match self {
161            Self::Definition(Nullable::Some(TermDefinition::Expanded(e))) => EntryValueSubItems::TermDefinitionFragment(Box::new(e.iter())),
162            _ => EntryValueSubItems::None,
163        }
164    }
165}
166
167/// Entry of a context definition, key and value together.
168pub enum EntryRef<'a> {
169    /// The `@base` entry, setting the base IRI against which relative IRIs are resolved.
170    Base(Nullable<&'a IriRefBuf>),
171    /// The `@import` entry, referencing a context to merge into this one.
172    Import(&'a IriRefBuf),
173    /// The `@language` entry, tagging string values with a language.
174    Language(Nullable<&'a LenientLangTagBuf>),
175    /// The `@direction` entry, setting the base direction of string values.
176    Direction(Nullable<Direction>),
177    /// The `@propagate` entry, controlling whether the context survives into node objects.
178    Propagate(bool),
179    /// The `@protected` entry, forbidding redefinition of the terms defined here.
180    Protected(bool),
181    /// The `@type` entry, setting how the node types of the described documents
182    /// are laid out and whether that setting is protected.
183    Type(Type),
184    /// The `@version` entry, declaring the processing mode.
185    Version(Version),
186    /// The `@vocab` entry, setting the vocabulary against which terms expand.
187    Vocab(Nullable<&'a Vocab>),
188    /// A term binding: the term and the definition bound to it.
189    Definition(&'a Key, Nullable<&'a TermDefinition>),
190}
191
192#[derive(Clone, Copy, PartialEq, Eq)]
193/// Key of a context definition entry.
194pub enum EntryKeyRef<'a> {
195    /// The `@base` entry, setting the base IRI against which relative IRIs are resolved.
196    Base,
197    /// The `@import` entry, referencing a context to merge into this one.
198    Import,
199    /// The `@language` entry, tagging string values with a language.
200    Language,
201    /// The `@direction` entry, setting the base direction of string values.
202    Direction,
203    /// The `@propagate` entry, controlling whether the context survives into node objects.
204    Propagate,
205    /// The `@protected` entry, forbidding redefinition of the terms defined here.
206    Protected,
207    /// The `@type` entry, setting how the node types of the described documents
208    /// are laid out and whether that setting is protected.
209    Type,
210    /// The `@version` entry, declaring the processing mode.
211    Version,
212    /// The `@vocab` entry, setting the vocabulary against which terms expand.
213    Vocab,
214    /// The term of a term binding.
215    Definition(&'a Key),
216}
217
218impl<'a> EntryKeyRef<'a> {
219    /// Returns this key as it is spelled in the context, such as `"@vocab"` or
220    /// the term itself.
221    #[must_use]
222    pub fn as_str(&self) -> &'a str {
223        match self {
224            Self::Base => "@base",
225            Self::Import => "@import",
226            Self::Language => "@language",
227            Self::Direction => "@direction",
228            Self::Propagate => "@propagate",
229            Self::Protected => "@protected",
230            Self::Type => "@type",
231            Self::Version => "@version",
232            Self::Vocab => "@vocab",
233            Self::Definition(d) => d.as_str(),
234        }
235    }
236}
237
238impl<'a> EntryRef<'a> {
239    /// Returns the key of this entry, taking `self` by value.
240    #[must_use]
241    pub fn into_key(self) -> EntryKeyRef<'a> {
242        match self {
243            Self::Base(_) => EntryKeyRef::Base,
244            Self::Import(_) => EntryKeyRef::Import,
245            Self::Language(_) => EntryKeyRef::Language,
246            Self::Direction(_) => EntryKeyRef::Direction,
247            Self::Propagate(_) => EntryKeyRef::Propagate,
248            Self::Protected(_) => EntryKeyRef::Protected,
249            Self::Type(_) => EntryKeyRef::Type,
250            Self::Version(_) => EntryKeyRef::Version,
251            Self::Vocab(_) => EntryKeyRef::Vocab,
252            Self::Definition(key, _) => EntryKeyRef::Definition(key),
253        }
254    }
255
256    /// Returns the key of this entry.
257    #[must_use]
258    pub fn key(&self) -> EntryKeyRef<'a> {
259        match self {
260            Self::Base(_) => EntryKeyRef::Base,
261            Self::Import(_) => EntryKeyRef::Import,
262            Self::Language(_) => EntryKeyRef::Language,
263            Self::Direction(_) => EntryKeyRef::Direction,
264            Self::Propagate(_) => EntryKeyRef::Propagate,
265            Self::Protected(_) => EntryKeyRef::Protected,
266            Self::Type(_) => EntryKeyRef::Type,
267            Self::Version(_) => EntryKeyRef::Version,
268            Self::Vocab(_) => EntryKeyRef::Vocab,
269            Self::Definition(key, _) => EntryKeyRef::Definition(key),
270        }
271    }
272
273    /// Returns the value of this entry, taking `self` by value.
274    #[must_use]
275    pub fn into_value(self) -> EntryValueRef<'a> {
276        match self {
277            Self::Base(v) => EntryValueRef::Base(v),
278            Self::Import(v) => EntryValueRef::Import(v),
279            Self::Language(v) => EntryValueRef::Language(v),
280            Self::Direction(v) => EntryValueRef::Direction(v),
281            Self::Propagate(v) => EntryValueRef::Propagate(v),
282            Self::Protected(v) => EntryValueRef::Protected(v),
283            Self::Type(v) => EntryValueRef::Type(v),
284            Self::Version(v) => EntryValueRef::Version(v),
285            Self::Vocab(v) => EntryValueRef::Vocab(v),
286            Self::Definition(_, b) => EntryValueRef::Definition(b),
287        }
288    }
289
290    /// Returns the value of this entry.
291    #[must_use]
292    pub fn value(&self) -> EntryValueRef<'a> {
293        match self {
294            Self::Base(v) => EntryValueRef::Base(*v),
295            Self::Import(v) => EntryValueRef::Import(v),
296            Self::Language(v) => EntryValueRef::Language(*v),
297            Self::Direction(v) => EntryValueRef::Direction(*v),
298            Self::Propagate(v) => EntryValueRef::Propagate(*v),
299            Self::Protected(v) => EntryValueRef::Protected(*v),
300            Self::Type(v) => EntryValueRef::Type(*v),
301            Self::Version(v) => EntryValueRef::Version(*v),
302            Self::Vocab(v) => EntryValueRef::Vocab(*v),
303            Self::Definition(_, b) => EntryValueRef::Definition(*b),
304        }
305    }
306
307    /// Returns the key and value of this entry, taking `self` by value.
308    #[must_use]
309    pub fn into_key_value(self) -> (EntryKeyRef<'a>, EntryValueRef<'a>) {
310        self.key_value()
311    }
312
313    /// Returns the key and value of this entry.
314    #[must_use]
315    pub fn key_value(&self) -> (EntryKeyRef<'a>, EntryValueRef<'a>) {
316        match self {
317            Self::Base(v) => (EntryKeyRef::Base, EntryValueRef::Base(*v)),
318            Self::Import(v) => (EntryKeyRef::Import, EntryValueRef::Import(v)),
319            Self::Language(v) => (EntryKeyRef::Language, EntryValueRef::Language(*v)),
320            Self::Direction(v) => (EntryKeyRef::Direction, EntryValueRef::Direction(*v)),
321            Self::Propagate(v) => (EntryKeyRef::Propagate, EntryValueRef::Propagate(*v)),
322            Self::Protected(v) => (EntryKeyRef::Protected, EntryValueRef::Protected(*v)),
323            Self::Type(v) => (EntryKeyRef::Type, EntryValueRef::Type(*v)),
324            Self::Version(v) => (EntryKeyRef::Version, EntryValueRef::Version(*v)),
325            Self::Vocab(v) => (EntryKeyRef::Vocab, EntryValueRef::Vocab(*v)),
326            Self::Definition(key, b) => (EntryKeyRef::Definition(key), EntryValueRef::Definition(*b)),
327        }
328    }
329}