json_ld_syntax/context/definition/
mod.rs

1use super::{term_definition, TermDefinition};
2use crate::{Direction, Keyword, LenientLangTagBuf, Nullable};
3use educe::Educe;
4use indexmap::IndexMap;
5use iref::IriRefBuf;
6
7mod import;
8mod key;
9mod reference;
10mod type_;
11mod version;
12mod vocab;
13
14pub use import::*;
15pub use key::*;
16pub use reference::*;
17pub use type_::*;
18pub use version::*;
19pub use vocab::*;
20
21/// Context definition.
22#[derive(PartialEq, Eq, Clone, Educe, Debug)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24#[educe(Default)]
25pub struct Definition {
26	#[cfg_attr(
27		feature = "serde",
28		serde(
29			rename = "@base",
30			default,
31			deserialize_with = "Nullable::optional",
32			skip_serializing_if = "Option::is_none"
33		)
34	)]
35	pub base: Option<Nullable<IriRefBuf>>,
36
37	#[cfg_attr(
38		feature = "serde",
39		serde(rename = "@import", default, skip_serializing_if = "Option::is_none")
40	)]
41	pub import: Option<IriRefBuf>,
42
43	#[cfg_attr(
44		feature = "serde",
45		serde(
46			rename = "@language",
47			default,
48			deserialize_with = "Nullable::optional",
49			skip_serializing_if = "Option::is_none"
50		)
51	)]
52	pub language: Option<Nullable<LenientLangTagBuf>>,
53
54	#[cfg_attr(
55		feature = "serde",
56		serde(
57			rename = "@direction",
58			default,
59			deserialize_with = "Nullable::optional",
60			skip_serializing_if = "Option::is_none"
61		)
62	)]
63	pub direction: Option<Nullable<Direction>>,
64
65	#[cfg_attr(
66		feature = "serde",
67		serde(
68			rename = "@propagate",
69			default,
70			skip_serializing_if = "Option::is_none"
71		)
72	)]
73	pub propagate: Option<bool>,
74
75	#[cfg_attr(
76		feature = "serde",
77		serde(
78			rename = "@protected",
79			default,
80			skip_serializing_if = "Option::is_none"
81		)
82	)]
83	pub protected: Option<bool>,
84
85	#[cfg_attr(
86		feature = "serde",
87		serde(rename = "@type", default, skip_serializing_if = "Option::is_none")
88	)]
89	pub type_: Option<Type>,
90
91	#[cfg_attr(
92		feature = "serde",
93		serde(rename = "@version", default, skip_serializing_if = "Option::is_none")
94	)]
95	pub version: Option<Version>,
96
97	#[cfg_attr(
98		feature = "serde",
99		serde(
100			rename = "@vocab",
101			default,
102			deserialize_with = "Nullable::optional",
103			skip_serializing_if = "Option::is_none"
104		)
105	)]
106	pub vocab: Option<Nullable<Vocab>>,
107
108	#[cfg_attr(feature = "serde", serde(flatten))]
109	pub bindings: Bindings,
110}
111
112impl Definition {
113	pub fn new() -> Self {
114		Self::default()
115	}
116
117	pub fn get(&self, key: &KeyOrKeyword) -> Option<EntryValueRef> {
118		match key {
119			KeyOrKeyword::Keyword(k) => match k {
120				Keyword::Base => self
121					.base
122					.as_ref()
123					.map(Nullable::as_deref)
124					.map(EntryValueRef::Base),
125				Keyword::Import => self.import.as_deref().map(EntryValueRef::Import),
126				Keyword::Language => self
127					.language
128					.as_ref()
129					.map(Nullable::as_ref)
130					.map(EntryValueRef::Language),
131				Keyword::Direction => self.direction.map(EntryValueRef::Direction),
132				Keyword::Propagate => self.propagate.map(EntryValueRef::Propagate),
133				Keyword::Protected => self.protected.map(EntryValueRef::Protected),
134				Keyword::Type => self.type_.map(EntryValueRef::Type),
135				Keyword::Version => self.version.map(EntryValueRef::Version),
136				Keyword::Vocab => self
137					.vocab
138					.as_ref()
139					.map(Nullable::as_ref)
140					.map(EntryValueRef::Vocab),
141				_ => None,
142			},
143			KeyOrKeyword::Key(k) => self.bindings.get(k).map(EntryValueRef::Definition),
144		}
145	}
146
147	pub fn get_binding(&self, key: &Key) -> Option<Nullable<&TermDefinition>> {
148		self.bindings.get(key)
149	}
150}
151
152/// Context bindings.
153#[derive(PartialEq, Eq, Clone, Educe, Debug)]
154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
155#[cfg_attr(feature = "serde", serde(transparent))]
156#[educe(Default)]
157pub struct Bindings(IndexMap<Key, Nullable<TermDefinition>>);
158
159pub struct BindingsIter<'a>(indexmap::map::Iter<'a, Key, Nullable<TermDefinition>>);
160
161impl<'a> Iterator for BindingsIter<'a> {
162	type Item = (&'a Key, Nullable<&'a TermDefinition>);
163
164	fn next(&mut self) -> Option<Self::Item> {
165		self.0.next().map(|(k, d)| (k, d.as_ref()))
166	}
167}
168
169impl<'a> DoubleEndedIterator for BindingsIter<'a> {
170	fn next_back(&mut self) -> Option<Self::Item> {
171		self.0.next_back().map(|(k, d)| (k, d.as_ref()))
172	}
173}
174
175impl<'a> ExactSizeIterator for BindingsIter<'a> {}
176
177impl Bindings {
178	pub fn insert(
179		&mut self,
180		key: Key,
181		def: Nullable<TermDefinition>,
182	) -> Option<Nullable<TermDefinition>> {
183		self.0.insert(key, def)
184	}
185}
186
187impl Bindings {
188	pub fn new() -> Self {
189		Self::default()
190	}
191
192	pub fn len(&self) -> usize {
193		self.0.len()
194	}
195
196	pub fn is_empty(&self) -> bool {
197		self.0.is_empty()
198	}
199
200	pub fn get(&self, key: &Key) -> Option<Nullable<&TermDefinition>> {
201		self.0.get(key).map(Nullable::as_ref)
202	}
203
204	pub fn get_entry(&self, i: usize) -> Option<(&Key, Nullable<&TermDefinition>)> {
205		self.0
206			.get_index(i)
207			.map(|(key, value)| (key, value.as_ref()))
208	}
209
210	pub fn iter(&self) -> BindingsIter {
211		BindingsIter(self.0.iter())
212	}
213
214	pub fn insert_with(
215		&mut self,
216		key: Key,
217		def: Nullable<TermDefinition>,
218	) -> Option<Nullable<TermDefinition>> {
219		self.0.insert(key, def)
220	}
221}
222
223impl IntoIterator for Bindings {
224	type Item = (Key, Nullable<TermDefinition>);
225	type IntoIter = indexmap::map::IntoIter<Key, Nullable<TermDefinition>>;
226
227	fn into_iter(self) -> Self::IntoIter {
228		self.0.into_iter()
229	}
230}
231
232impl FromIterator<(Key, Nullable<TermDefinition>)> for Bindings {
233	fn from_iter<T: IntoIterator<Item = (Key, Nullable<TermDefinition>)>>(iter: T) -> Self {
234		let mut result = Self::new();
235
236		for (key, binding) in iter {
237			result.0.insert(key, binding);
238		}
239
240		result
241	}
242}
243
244/// Context definition fragment.
245pub enum FragmentRef<'a> {
246	/// Context definition entry.
247	Entry(EntryRef<'a>),
248
249	/// Context definition entry key.
250	Key(EntryKeyRef<'a>),
251
252	/// Context definition entry value.
253	Value(EntryValueRef<'a>),
254
255	/// Term definition fragment.
256	TermDefinitionFragment(term_definition::FragmentRef<'a>),
257}
258
259impl<'a> FragmentRef<'a> {
260	pub fn is_key(&self) -> bool {
261		match self {
262			Self::Key(_) => true,
263			Self::TermDefinitionFragment(f) => f.is_key(),
264			_ => false,
265		}
266	}
267
268	pub fn is_entry(&self) -> bool {
269		match self {
270			Self::Entry(_) => true,
271			Self::TermDefinitionFragment(f) => f.is_entry(),
272			_ => false,
273		}
274	}
275
276	pub fn is_array(&self) -> bool {
277		match self {
278			Self::TermDefinitionFragment(i) => i.is_array(),
279			_ => false,
280		}
281	}
282
283	pub fn is_object(&self) -> bool {
284		match self {
285			Self::Value(v) => v.is_object(),
286			Self::TermDefinitionFragment(v) => v.is_object(),
287			_ => false,
288		}
289	}
290
291	pub fn sub_items(&self) -> SubItems<'a> {
292		match self {
293			Self::Entry(e) => SubItems::Entry(Some(e.key()), Some(Box::new(e.value()))),
294			Self::Key(_) => SubItems::None,
295			Self::Value(v) => SubItems::Value(v.sub_items()),
296			Self::TermDefinitionFragment(f) => SubItems::TermDefinitionFragment(f.sub_fragments()),
297		}
298	}
299}
300
301pub enum EntryValueSubItems<'a> {
302	None,
303	TermDefinitionFragment(Box<term_definition::Entries<'a>>),
304}
305
306impl<'a> Iterator for EntryValueSubItems<'a> {
307	type Item = FragmentRef<'a>;
308
309	fn next(&mut self) -> Option<Self::Item> {
310		match self {
311			Self::None => None,
312			Self::TermDefinitionFragment(d) => d.next().map(|e| {
313				FragmentRef::TermDefinitionFragment(term_definition::FragmentRef::Entry(e))
314			}),
315		}
316	}
317}
318
319pub enum SubItems<'a> {
320	None,
321	Entry(Option<EntryKeyRef<'a>>, Option<Box<EntryValueRef<'a>>>),
322	Value(EntryValueSubItems<'a>),
323	TermDefinitionFragment(term_definition::SubFragments<'a>),
324}
325
326impl<'a> Iterator for SubItems<'a> {
327	type Item = FragmentRef<'a>;
328
329	fn next(&mut self) -> Option<Self::Item> {
330		match self {
331			Self::None => None,
332			Self::Entry(k, v) => k
333				.take()
334				.map(FragmentRef::Key)
335				.or_else(|| v.take().map(|v| FragmentRef::Value(*v))),
336			Self::Value(d) => d.next(),
337			Self::TermDefinitionFragment(d) => d.next().map(FragmentRef::TermDefinitionFragment),
338		}
339	}
340}
341
342#[cfg(test)]
343mod tests {
344	use super::Definition;
345
346	#[test]
347	fn deserialize_null_vocab() {
348		let definition: Definition = json_syntax::from_value(json_syntax::json!({
349			"@vocab": null
350		}))
351		.unwrap();
352		assert_eq!(definition.vocab, Some(crate::Nullable::Null))
353	}
354
355	#[test]
356	fn deserialize_no_vocab() {
357		let definition: Definition = json_syntax::from_value(json_syntax::json!({})).unwrap();
358		assert_eq!(definition.vocab, None)
359	}
360}