json_ld_syntax/context/term_definition/
mod.rs

1use crate::{
2	container, context, CompactIri, CompactIriBuf, Container, ContainerKind, Direction, Keyword,
3	LenientLangTag, LenientLangTagBuf, Nullable,
4};
5use educe::Educe;
6use iref::{Iri, IriBuf};
7use rdf_types::{BlankId, BlankIdBuf};
8
9mod id;
10mod index;
11mod nest;
12mod type_;
13
14pub use id::*;
15pub use index::*;
16pub use nest::*;
17pub use type_::*;
18
19/// Term definition.
20#[derive(PartialEq, Eq, Clone, Debug)]
21#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
22#[cfg_attr(feature = "serde", serde(untagged))]
23pub enum TermDefinition {
24	Simple(Simple),
25	Expanded(Box<Expanded>),
26}
27
28impl TermDefinition {
29	pub fn is_expanded(&self) -> bool {
30		matches!(self, Self::Expanded(_))
31	}
32
33	pub fn is_object(&self) -> bool {
34		self.is_expanded()
35	}
36
37	pub fn as_expanded(&self) -> ExpandedRef {
38		match self {
39			Self::Simple(term) => ExpandedRef {
40				id: Some(Nullable::Some(term.as_str().into())),
41				..Default::default()
42			},
43			Self::Expanded(e) => e.as_expanded_ref(),
44		}
45	}
46}
47
48#[derive(PartialEq, Eq, Clone, Debug)]
49#[cfg_attr(
50	feature = "serde",
51	derive(serde::Serialize, serde::Deserialize),
52	serde(transparent)
53)]
54pub struct Simple(pub(crate) String);
55
56impl Simple {
57	pub fn as_iri(&self) -> Option<&Iri> {
58		Iri::new(&self.0).ok()
59	}
60
61	pub fn as_compact_iri(&self) -> Option<&CompactIri> {
62		CompactIri::new(&self.0).ok()
63	}
64
65	pub fn as_blank_id(&self) -> Option<&BlankId> {
66		BlankId::new(&self.0).ok()
67	}
68
69	pub fn as_str(&self) -> &str {
70		&self.0
71	}
72
73	pub fn into_string(self) -> String {
74		self.0
75	}
76}
77
78impl From<IriBuf> for Simple {
79	fn from(value: IriBuf) -> Self {
80		Self(value.into_string())
81	}
82}
83
84impl From<CompactIriBuf> for Simple {
85	fn from(value: CompactIriBuf) -> Self {
86		Self(value.into_string())
87	}
88}
89
90impl From<BlankIdBuf> for Simple {
91	fn from(value: BlankIdBuf) -> Self {
92		Self(value.to_string())
93	}
94}
95
96/// Expanded term definition.
97#[derive(PartialEq, Eq, Clone, Educe, Debug)]
98#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
99#[educe(Default)]
100pub struct Expanded {
101	#[cfg_attr(
102		feature = "serde",
103		serde(
104			rename = "@id",
105			default,
106			deserialize_with = "Nullable::optional",
107			skip_serializing_if = "Option::is_none"
108		)
109	)]
110	pub id: Option<Nullable<Id>>,
111
112	#[cfg_attr(
113		feature = "serde",
114		serde(
115			rename = "@type",
116			default,
117			deserialize_with = "Nullable::optional",
118			skip_serializing_if = "Option::is_none"
119		)
120	)]
121	pub type_: Option<Nullable<Type>>,
122
123	#[cfg_attr(
124		feature = "serde",
125		serde(rename = "@context", default, skip_serializing_if = "Option::is_none")
126	)]
127	pub context: Option<Box<context::Context>>,
128
129	#[cfg_attr(
130		feature = "serde",
131		serde(rename = "@reverse", default, skip_serializing_if = "Option::is_none")
132	)]
133	pub reverse: Option<context::definition::Key>,
134
135	#[cfg_attr(
136		feature = "serde",
137		serde(rename = "@index", default, skip_serializing_if = "Option::is_none")
138	)]
139	pub index: Option<Index>,
140
141	#[cfg_attr(
142		feature = "serde",
143		serde(
144			rename = "@language",
145			default,
146			deserialize_with = "Nullable::optional",
147			skip_serializing_if = "Option::is_none"
148		)
149	)]
150	pub language: Option<Nullable<LenientLangTagBuf>>,
151
152	#[cfg_attr(
153		feature = "serde",
154		serde(
155			rename = "@direction",
156			default,
157			deserialize_with = "Nullable::optional",
158			skip_serializing_if = "Option::is_none"
159		)
160	)]
161	pub direction: Option<Nullable<Direction>>,
162
163	#[cfg_attr(
164		feature = "serde",
165		serde(
166			rename = "@container",
167			default,
168			deserialize_with = "Nullable::optional",
169			skip_serializing_if = "Option::is_none"
170		)
171	)]
172	pub container: Option<Nullable<Container>>,
173
174	#[cfg_attr(
175		feature = "serde",
176		serde(rename = "@nest", default, skip_serializing_if = "Option::is_none")
177	)]
178	pub nest: Option<Nest>,
179
180	#[cfg_attr(
181		feature = "serde",
182		serde(rename = "@prefix", default, skip_serializing_if = "Option::is_none")
183	)]
184	pub prefix: Option<bool>,
185
186	#[cfg_attr(
187		feature = "serde",
188		serde(
189			rename = "@propagate",
190			default,
191			skip_serializing_if = "Option::is_none"
192		)
193	)]
194	pub propagate: Option<bool>,
195
196	#[cfg_attr(
197		feature = "serde",
198		serde(
199			rename = "@protected",
200			default,
201			skip_serializing_if = "Option::is_none"
202		)
203	)]
204	pub protected: Option<bool>,
205}
206
207impl Expanded {
208	pub fn new() -> Self {
209		Self::default()
210	}
211
212	pub fn is_null(&self) -> bool {
213		matches!(&self.id, None | Some(Nullable::Null))
214			&& self.type_.is_none()
215			&& self.context.is_none()
216			&& self.reverse.is_none()
217			&& self.index.is_none()
218			&& self.language.is_none()
219			&& self.direction.is_none()
220			&& self.container.is_none()
221			&& self.nest.is_none()
222			&& self.prefix.is_none()
223			&& self.propagate.is_none()
224			&& self.protected.is_none()
225	}
226
227	pub fn is_simple_definition(&self) -> bool {
228		matches!(&self.id, Some(Nullable::Some(_)))
229			&& self.type_.is_none()
230			&& self.context.is_none()
231			&& self.reverse.is_none()
232			&& self.index.is_none()
233			&& self.language.is_none()
234			&& self.direction.is_none()
235			&& self.container.is_none()
236			&& self.nest.is_none()
237			&& self.prefix.is_none()
238			&& self.propagate.is_none()
239			&& self.protected.is_none()
240	}
241
242	pub fn simplify(self) -> Nullable<TermDefinition> {
243		if self.is_null() {
244			Nullable::Null
245		} else if self.is_simple_definition() {
246			Nullable::Some(TermDefinition::Simple(Simple(
247				self.id.unwrap().unwrap().into_string(),
248			)))
249		} else {
250			Nullable::Some(TermDefinition::Expanded(Box::new(self)))
251		}
252	}
253
254	pub fn iter(&self) -> Entries {
255		Entries {
256			id: self.id.as_ref().map(Nullable::as_ref),
257			type_: self.type_.as_ref().map(Nullable::as_ref),
258			context: self.context.as_deref(),
259			reverse: self.reverse.as_ref(),
260			index: self.index.as_ref(),
261			language: self.language.as_ref().map(Nullable::as_ref),
262			direction: self.direction,
263			container: self.container.as_ref().map(Nullable::as_ref),
264			nest: self.nest.as_ref(),
265			prefix: self.prefix,
266			propagate: self.propagate,
267			protected: self.protected,
268		}
269	}
270
271	pub fn as_expanded_ref(&self) -> ExpandedRef {
272		ExpandedRef {
273			id: self
274				.id
275				.as_ref()
276				.map(|i| i.as_ref().map(|id| id.as_id_ref())),
277			type_: self.type_.as_ref().map(Nullable::as_ref),
278			context: self.context.as_deref(),
279			reverse: self.reverse.as_ref(),
280			index: self.index.as_ref(),
281			language: self
282				.language
283				.as_ref()
284				.map(|n| n.as_ref().map(LenientLangTagBuf::as_lenient_lang_tag_ref)),
285			direction: self.direction,
286			container: self.container.as_ref().map(Nullable::as_ref),
287			nest: self.nest.as_ref(),
288			prefix: self.prefix,
289			propagate: self.propagate,
290			protected: self.protected,
291		}
292	}
293}
294
295/// Expanded term definition.
296#[derive(Debug, Educe)]
297#[educe(Default)]
298pub struct ExpandedRef<'a> {
299	pub id: Option<Nullable<IdRef<'a>>>,
300	pub type_: Option<Nullable<&'a Type>>,
301	pub context: Option<&'a context::Context>,
302	pub reverse: Option<&'a context::definition::Key>,
303	pub index: Option<&'a Index>,
304	pub language: Option<Nullable<&'a LenientLangTag>>,
305	pub direction: Option<Nullable<Direction>>,
306	pub container: Option<Nullable<&'a Container>>,
307	pub nest: Option<&'a Nest>,
308	pub prefix: Option<bool>,
309	pub propagate: Option<bool>,
310	pub protected: Option<bool>,
311}
312
313impl<'a> From<Nullable<&'a TermDefinition>> for ExpandedRef<'a> {
314	fn from(value: Nullable<&'a TermDefinition>) -> Self {
315		match value {
316			Nullable::Some(d) => d.as_expanded(),
317			Nullable::Null => Self {
318				id: Some(Nullable::Null),
319				..Default::default()
320			},
321		}
322	}
323}
324
325/// Term definition entries.
326pub struct Entries<'a> {
327	id: Option<Nullable<&'a Id>>,
328	type_: Option<Nullable<&'a Type>>,
329	context: Option<&'a context::Context>,
330	reverse: Option<&'a context::definition::Key>,
331	index: Option<&'a Index>,
332	language: Option<Nullable<&'a LenientLangTagBuf>>,
333	direction: Option<Nullable<Direction>>,
334	container: Option<Nullable<&'a Container>>,
335	nest: Option<&'a Nest>,
336	prefix: Option<bool>,
337	propagate: Option<bool>,
338	protected: Option<bool>,
339}
340
341pub enum EntryRef<'a> {
342	Id(Nullable<&'a Id>),
343	Type(Nullable<&'a Type>),
344	Context(&'a context::Context),
345	Reverse(&'a context::definition::Key),
346	Index(&'a Index),
347	Language(Nullable<&'a LenientLangTagBuf>),
348	Direction(Nullable<Direction>),
349	Container(Nullable<&'a Container>),
350	Nest(&'a Nest),
351	Prefix(bool),
352	Propagate(bool),
353	Protected(bool),
354}
355
356impl<'a> EntryRef<'a> {
357	pub fn into_key(self) -> EntryKey {
358		match self {
359			Self::Id(_) => EntryKey::Id,
360			Self::Type(_) => EntryKey::Type,
361			Self::Context(_) => EntryKey::Context,
362			Self::Reverse(_) => EntryKey::Reverse,
363			Self::Index(_) => EntryKey::Index,
364			Self::Language(_) => EntryKey::Language,
365			Self::Direction(_) => EntryKey::Direction,
366			Self::Container(_) => EntryKey::Container,
367			Self::Nest(_) => EntryKey::Nest,
368			Self::Prefix(_) => EntryKey::Prefix,
369			Self::Propagate(_) => EntryKey::Propagate,
370			Self::Protected(_) => EntryKey::Protected,
371		}
372	}
373
374	pub fn key(&self) -> EntryKey {
375		match self {
376			Self::Id(_) => EntryKey::Id,
377			Self::Type(_) => EntryKey::Type,
378			Self::Context(_) => EntryKey::Context,
379			Self::Reverse(_) => EntryKey::Reverse,
380			Self::Index(_) => EntryKey::Index,
381			Self::Language(_) => EntryKey::Language,
382			Self::Direction(_) => EntryKey::Direction,
383			Self::Container(_) => EntryKey::Container,
384			Self::Nest(_) => EntryKey::Nest,
385			Self::Prefix(_) => EntryKey::Prefix,
386			Self::Propagate(_) => EntryKey::Propagate,
387			Self::Protected(_) => EntryKey::Protected,
388		}
389	}
390
391	pub fn into_value(self) -> EntryValueRef<'a> {
392		self.value()
393	}
394
395	pub fn value(&self) -> EntryValueRef<'a> {
396		match self {
397			Self::Id(e) => EntryValueRef::Id(*e),
398			Self::Type(e) => EntryValueRef::Type(*e),
399			Self::Context(e) => EntryValueRef::Context(e),
400			Self::Reverse(e) => EntryValueRef::Reverse(e),
401			Self::Index(e) => EntryValueRef::Index(e),
402			Self::Language(e) => EntryValueRef::Language(*e),
403			Self::Direction(e) => EntryValueRef::Direction(*e),
404			Self::Container(e) => EntryValueRef::Container(*e),
405			Self::Nest(e) => EntryValueRef::Nest(e),
406			Self::Prefix(e) => EntryValueRef::Prefix(*e),
407			Self::Propagate(e) => EntryValueRef::Propagate(*e),
408			Self::Protected(e) => EntryValueRef::Protected(*e),
409		}
410	}
411
412	pub fn into_key_value(self) -> (EntryKey, EntryValueRef<'a>) {
413		self.key_value()
414	}
415
416	pub fn key_value(&self) -> (EntryKey, EntryValueRef<'a>) {
417		match self {
418			Self::Id(e) => (EntryKey::Id, EntryValueRef::Id(*e)),
419			Self::Type(e) => (EntryKey::Type, EntryValueRef::Type(*e)),
420			Self::Context(e) => (EntryKey::Context, EntryValueRef::Context(e)),
421			Self::Reverse(e) => (EntryKey::Reverse, EntryValueRef::Reverse(e)),
422			Self::Index(e) => (EntryKey::Index, EntryValueRef::Index(e)),
423			Self::Language(e) => (EntryKey::Language, EntryValueRef::Language(*e)),
424			Self::Direction(e) => (EntryKey::Direction, EntryValueRef::Direction(*e)),
425			Self::Container(e) => (EntryKey::Container, EntryValueRef::Container(*e)),
426			Self::Nest(e) => (EntryKey::Nest, EntryValueRef::Nest(e)),
427			Self::Prefix(e) => (EntryKey::Prefix, EntryValueRef::Prefix(*e)),
428			Self::Propagate(e) => (EntryKey::Propagate, EntryValueRef::Propagate(*e)),
429			Self::Protected(e) => (EntryKey::Protected, EntryValueRef::Protected(*e)),
430		}
431	}
432}
433
434pub enum EntryKey {
435	Id,
436	Type,
437	Context,
438	Reverse,
439	Index,
440	Language,
441	Direction,
442	Container,
443	Nest,
444	Prefix,
445	Propagate,
446	Protected,
447}
448
449impl EntryKey {
450	pub fn keyword(&self) -> Keyword {
451		match self {
452			Self::Id => Keyword::Id,
453			Self::Type => Keyword::Type,
454			Self::Context => Keyword::Context,
455			Self::Reverse => Keyword::Reverse,
456			Self::Index => Keyword::Index,
457			Self::Language => Keyword::Language,
458			Self::Direction => Keyword::Direction,
459			Self::Container => Keyword::Container,
460			Self::Nest => Keyword::Nest,
461			Self::Prefix => Keyword::Prefix,
462			Self::Propagate => Keyword::Propagate,
463			Self::Protected => Keyword::Protected,
464		}
465	}
466
467	pub fn as_str(&self) -> &'static str {
468		self.keyword().into_str()
469	}
470}
471
472pub enum EntryValueRef<'a> {
473	Id(Nullable<&'a Id>),
474	Type(Nullable<&'a Type>),
475	Context(&'a context::Context),
476	Reverse(&'a context::definition::Key),
477	Index(&'a Index),
478	Language(Nullable<&'a LenientLangTagBuf>),
479	Direction(Nullable<Direction>),
480	Container(Nullable<&'a Container>),
481	Nest(&'a Nest),
482	Prefix(bool),
483	Propagate(bool),
484	Protected(bool),
485}
486
487impl<'a> EntryValueRef<'a> {
488	pub fn is_object(&self) -> bool {
489		match self {
490			Self::Context(c) => c.is_object(),
491			_ => false,
492		}
493	}
494
495	pub fn is_array(&self) -> bool {
496		match self {
497			Self::Container(Nullable::Some(c)) => c.is_array(),
498			_ => false,
499		}
500	}
501}
502
503impl<'a> Iterator for Entries<'a> {
504	type Item = EntryRef<'a>;
505
506	fn size_hint(&self) -> (usize, Option<usize>) {
507		let mut len = 0;
508
509		if self.id.is_some() {
510			len += 1
511		}
512
513		if self.type_.is_some() {
514			len += 1
515		}
516
517		if self.context.is_some() {
518			len += 1
519		}
520
521		if self.reverse.is_some() {
522			len += 1
523		}
524
525		if self.index.is_some() {
526			len += 1
527		}
528
529		if self.language.is_some() {
530			len += 1
531		}
532
533		if self.direction.is_some() {
534			len += 1
535		}
536
537		if self.container.is_some() {
538			len += 1
539		}
540
541		if self.nest.is_some() {
542			len += 1
543		}
544
545		if self.prefix.is_some() {
546			len += 1
547		}
548
549		if self.propagate.is_some() {
550			len += 1
551		}
552
553		if self.protected.is_some() {
554			len += 1
555		}
556
557		(len, Some(len))
558	}
559
560	fn next(&mut self) -> Option<Self::Item> {
561		match self.id.take() {
562			Some(value) => Some(EntryRef::Id(value)),
563			None => match self.type_.take() {
564				Some(value) => Some(EntryRef::Type(value)),
565				None => match self.context.take() {
566					Some(value) => Some(EntryRef::Context(value)),
567					None => match self.reverse.take() {
568						Some(value) => Some(EntryRef::Reverse(value)),
569						None => match self.index.take() {
570							Some(value) => Some(EntryRef::Index(value)),
571							None => match self.language.take() {
572								Some(value) => Some(EntryRef::Language(value)),
573								None => match self.direction.take() {
574									Some(value) => Some(EntryRef::Direction(value)),
575									None => match self.container.take() {
576										Some(value) => Some(EntryRef::Container(value)),
577										None => match self.nest.take() {
578											Some(value) => Some(EntryRef::Nest(value)),
579											None => match self.prefix.take() {
580												Some(value) => Some(EntryRef::Prefix(value)),
581												None => match self.propagate.take() {
582													Some(value) => Some(EntryRef::Propagate(value)),
583													None => self
584														.protected
585														.take()
586														.map(EntryRef::Protected),
587												},
588											},
589										},
590									},
591								},
592							},
593						},
594					},
595				},
596			},
597		}
598	}
599}
600
601impl<'a> ExactSizeIterator for Entries<'a> {}
602
603/// Term definition fragment.
604pub enum FragmentRef<'a> {
605	/// Term definition entry.
606	Entry(EntryRef<'a>),
607
608	/// Term definition entry key.
609	Key(EntryKey),
610
611	/// Term definition entry value.
612	Value(EntryValueRef<'a>),
613
614	/// Container value fragment.
615	ContainerFragment(&'a ContainerKind),
616}
617
618impl<'a> FragmentRef<'a> {
619	pub fn is_key(&self) -> bool {
620		matches!(self, Self::Key(_))
621	}
622
623	pub fn is_entry(&self) -> bool {
624		matches!(self, Self::Entry(_))
625	}
626
627	pub fn is_array(&self) -> bool {
628		match self {
629			Self::Value(v) => v.is_array(),
630			_ => false,
631		}
632	}
633
634	pub fn is_object(&self) -> bool {
635		match self {
636			Self::Value(v) => v.is_object(),
637			_ => false,
638		}
639	}
640
641	pub fn sub_fragments(&self) -> SubFragments<'a> {
642		match self {
643			Self::Value(EntryValueRef::Container(Nullable::Some(c))) => {
644				SubFragments::Container(c.sub_fragments())
645			}
646			_ => SubFragments::None,
647		}
648	}
649}
650
651pub enum SubFragments<'a> {
652	None,
653	Container(container::SubValues<'a>),
654}
655
656impl<'a> Iterator for SubFragments<'a> {
657	type Item = FragmentRef<'a>;
658
659	fn next(&mut self) -> Option<Self::Item> {
660		match self {
661			Self::None => None,
662			Self::Container(c) => c.next().map(FragmentRef::ContainerFragment),
663		}
664	}
665}