json_ld_syntax/context/
mod.rs

1use iref::{Iri, IriRef, IriRefBuf};
2use smallvec::SmallVec;
3
4pub mod definition;
5mod print;
6pub mod term_definition;
7mod try_from_json;
8
9pub use definition::Definition;
10pub use term_definition::TermDefinition;
11pub use try_from_json::InvalidContext;
12
13/// JSON-LD Context.
14///
15/// Can represent a single context entry, or a list of context entries.
16#[derive(PartialEq, Eq, Clone, Debug)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18#[cfg_attr(feature = "serde", serde(untagged))]
19pub enum Context {
20	One(ContextEntry),
21	Many(Vec<ContextEntry>),
22}
23
24impl Default for Context {
25	fn default() -> Self {
26		Self::Many(Vec::new())
27	}
28}
29
30impl Context {
31	/// Creates a new context with a single entry.
32	pub fn one(context: ContextEntry) -> Self {
33		Self::One(context)
34	}
35
36	/// Creates the `null` context.
37	pub fn null() -> Self {
38		Self::one(ContextEntry::Null)
39	}
40
41	/// Creates a new context with a single IRI-reference entry.
42	pub fn iri_ref(iri_ref: IriRefBuf) -> Self {
43		Self::one(ContextEntry::IriRef(iri_ref))
44	}
45
46	/// Creates a new context with a single context definition entry.
47	pub fn definition(def: Definition) -> Self {
48		Self::one(ContextEntry::Definition(def))
49	}
50}
51
52impl Context {
53	pub fn len(&self) -> usize {
54		match self {
55			Self::One(_) => 1,
56			Self::Many(l) => l.len(),
57		}
58	}
59
60	pub fn is_empty(&self) -> bool {
61		match self {
62			Self::One(_) => false,
63			Self::Many(l) => l.is_empty(),
64		}
65	}
66
67	pub fn as_slice(&self) -> &[ContextEntry] {
68		match self {
69			Self::One(c) => std::slice::from_ref(c),
70			Self::Many(list) => list,
71		}
72	}
73
74	pub fn is_object(&self) -> bool {
75		match self {
76			Self::One(c) => c.is_object(),
77			_ => false,
78		}
79	}
80
81	pub fn is_array(&self) -> bool {
82		matches!(self, Self::Many(_))
83	}
84
85	pub fn traverse(&self) -> Traverse {
86		match self {
87			Self::One(c) => Traverse::new(FragmentRef::Context(c)),
88			Self::Many(m) => Traverse::new(FragmentRef::ContextArray(m)),
89		}
90	}
91
92	pub fn iter(&self) -> std::slice::Iter<ContextEntry> {
93		self.as_slice().iter()
94	}
95}
96
97pub enum IntoIter {
98	One(Option<ContextEntry>),
99	Many(std::vec::IntoIter<ContextEntry>),
100}
101
102impl Iterator for IntoIter {
103	type Item = ContextEntry;
104
105	fn next(&mut self) -> Option<Self::Item> {
106		match self {
107			Self::One(t) => t.take(),
108			Self::Many(t) => t.next(),
109		}
110	}
111}
112
113impl IntoIterator for Context {
114	type Item = ContextEntry;
115	type IntoIter = IntoIter;
116
117	fn into_iter(self) -> Self::IntoIter {
118		match self {
119			Self::One(t) => IntoIter::One(Some(t)),
120			Self::Many(t) => IntoIter::Many(t.into_iter()),
121		}
122	}
123}
124
125impl<'a> IntoIterator for &'a Context {
126	type IntoIter = std::slice::Iter<'a, ContextEntry>;
127	type Item = &'a ContextEntry;
128
129	fn into_iter(self) -> Self::IntoIter {
130		self.iter()
131	}
132}
133
134impl From<ContextEntry> for Context {
135	fn from(c: ContextEntry) -> Self {
136		Self::One(c)
137	}
138}
139
140impl From<IriRefBuf> for Context {
141	fn from(i: IriRefBuf) -> Self {
142		Self::One(ContextEntry::IriRef(i))
143	}
144}
145
146impl<'a> From<&'a IriRef> for Context {
147	fn from(i: &'a IriRef) -> Self {
148		Self::One(ContextEntry::IriRef(i.to_owned()))
149	}
150}
151
152impl From<iref::IriBuf> for Context {
153	fn from(i: iref::IriBuf) -> Self {
154		Self::One(ContextEntry::IriRef(i.into()))
155	}
156}
157
158impl<'a> From<&'a Iri> for Context {
159	fn from(i: &'a Iri) -> Self {
160		Self::One(ContextEntry::IriRef(i.to_owned().into()))
161	}
162}
163
164impl From<Definition> for Context {
165	fn from(c: Definition) -> Self {
166		Self::One(ContextEntry::Definition(c))
167	}
168}
169
170/// Context.
171#[derive(PartialEq, Eq, Clone, Debug)]
172#[cfg_attr(
173	feature = "serde",
174	derive(serde::Serialize, serde::Deserialize),
175	serde(untagged)
176)]
177pub enum ContextEntry {
178	Null,
179	IriRef(IriRefBuf),
180	Definition(Definition),
181}
182
183impl ContextEntry {
184	fn sub_items(&self) -> ContextSubFragments {
185		match self {
186			Self::Definition(d) => ContextSubFragments::Definition(Box::new(d.iter())),
187			_ => ContextSubFragments::None,
188		}
189	}
190
191	pub fn is_object(&self) -> bool {
192		matches!(self, Self::Definition(_))
193	}
194}
195
196impl From<IriRefBuf> for ContextEntry {
197	fn from(i: IriRefBuf) -> Self {
198		ContextEntry::IriRef(i)
199	}
200}
201
202impl<'a> From<&'a IriRef> for ContextEntry {
203	fn from(i: &'a IriRef) -> Self {
204		ContextEntry::IriRef(i.to_owned())
205	}
206}
207
208impl From<iref::IriBuf> for ContextEntry {
209	fn from(i: iref::IriBuf) -> Self {
210		ContextEntry::IriRef(i.into())
211	}
212}
213
214impl<'a> From<&'a Iri> for ContextEntry {
215	fn from(i: &'a Iri) -> Self {
216		ContextEntry::IriRef(i.to_owned().into())
217	}
218}
219
220impl From<Definition> for ContextEntry {
221	fn from(c: Definition) -> Self {
222		ContextEntry::Definition(c)
223	}
224}
225
226/// Context value fragment.
227pub enum FragmentRef<'a> {
228	/// Context array.
229	ContextArray(&'a [ContextEntry]),
230
231	/// Context.
232	Context(&'a ContextEntry),
233
234	/// Context definition fragment.
235	DefinitionFragment(definition::FragmentRef<'a>),
236}
237
238impl<'a> FragmentRef<'a> {
239	pub fn is_array(&self) -> bool {
240		match self {
241			Self::ContextArray(_) => true,
242			Self::DefinitionFragment(i) => i.is_array(),
243			_ => false,
244		}
245	}
246
247	pub fn is_object(&self) -> bool {
248		match self {
249			Self::Context(c) => c.is_object(),
250			Self::DefinitionFragment(i) => i.is_object(),
251			_ => false,
252		}
253	}
254
255	pub fn sub_items(&self) -> SubFragments<'a> {
256		match self {
257			Self::ContextArray(a) => SubFragments::ContextArray(a.iter()),
258			Self::Context(c) => SubFragments::Context(c.sub_items()),
259			Self::DefinitionFragment(d) => SubFragments::Definition(Box::new(d.sub_items())),
260		}
261	}
262}
263
264pub enum ContextSubFragments<'a> {
265	None,
266	Definition(Box<definition::Entries<'a>>),
267}
268
269impl<'a> Iterator for ContextSubFragments<'a> {
270	type Item = FragmentRef<'a>;
271
272	fn next(&mut self) -> Option<Self::Item> {
273		match self {
274			Self::None => None,
275			Self::Definition(e) => e
276				.next()
277				.map(|e| FragmentRef::DefinitionFragment(definition::FragmentRef::Entry(e))),
278		}
279	}
280}
281
282pub enum SubFragments<'a> {
283	ContextArray(std::slice::Iter<'a, ContextEntry>),
284	Context(ContextSubFragments<'a>),
285	Definition(Box<definition::SubItems<'a>>),
286}
287
288impl<'a> Iterator for SubFragments<'a> {
289	type Item = FragmentRef<'a>;
290
291	fn next(&mut self) -> Option<Self::Item> {
292		match self {
293			Self::ContextArray(a) => a.next().map(FragmentRef::Context),
294			Self::Context(i) => i.next(),
295			Self::Definition(i) => i.next().map(FragmentRef::DefinitionFragment),
296		}
297	}
298}
299
300pub struct Traverse<'a> {
301	stack: SmallVec<[FragmentRef<'a>; 8]>,
302}
303
304impl<'a> Traverse<'a> {
305	pub(crate) fn new(item: FragmentRef<'a>) -> Self {
306		let mut stack = SmallVec::new();
307		stack.push(item);
308		Self { stack }
309	}
310}
311
312impl<'a> Iterator for Traverse<'a> {
313	type Item = FragmentRef<'a>;
314
315	fn next(&mut self) -> Option<Self::Item> {
316		match self.stack.pop() {
317			Some(item) => {
318				self.stack.extend(item.sub_items());
319				Some(item)
320			}
321			None => None,
322		}
323	}
324}
325
326/// Context document.
327///
328/// A context document is a JSON-LD document containing an object with a single
329/// `@context` entry.
330#[derive(PartialEq, Eq, Clone, Debug)]
331#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
332pub struct ContextDocument {
333	#[cfg_attr(feature = "serde", serde(rename = "@context"))]
334	pub context: Context,
335}