1use super::{IntoSyntax, Nest};
2use crate::{Container, Direction, HashMap, LenientLangTagBuf, Nullable, Term, Type, ValidId as Id};
3use contextual::WithContext;
4use iri_rs::IriBuf;
5use jsonld_syntax::{
6 KeywordType,
7 context::{
8 definition::{Key, TypeContainer},
9 term_definition::Index,
10 },
11};
12use rdfx::{
13 BlankIdBuf,
14 vocabulary::{IriVocabulary, Vocabulary},
15};
16use std::{borrow::Borrow, fmt, hash::Hash, sync::Arc};
17
18pub enum Binding<T = IriBuf, B = BlankIdBuf> {
20 Normal(Key, NormalTermDefinition<T, B>),
22
23 Type(TypeTermDefinition),
25}
26
27pub enum BindingRef<'a, T, B> {
29 Normal(&'a Key, &'a NormalTermDefinition<T, B>),
31
32 Type(&'a TypeTermDefinition),
34}
35
36pub enum BindingTerm<'a> {
38 Normal(&'a Key),
40 Type,
42}
43
44impl<'a> BindingTerm<'a> {
45 #[must_use]
47 pub fn as_str(&self) -> &'a str {
48 match self {
49 Self::Normal(key) => key.as_str(),
50 Self::Type => "@type",
51 }
52 }
53}
54
55impl fmt::Display for BindingTerm<'_> {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 self.as_str().fmt(f)
58 }
59}
60
61impl<'a, T, B> BindingRef<'a, T, B> {
62 #[must_use]
64 pub fn term(&self) -> BindingTerm<'a> {
65 match self {
66 Self::Normal(key, _) => BindingTerm::Normal(key),
67 Self::Type(_) => BindingTerm::Type,
68 }
69 }
70
71 #[must_use]
73 pub fn definition(&self) -> TermDefinitionRef<'a, T, B> {
74 match self {
75 Self::Normal(_, d) => TermDefinitionRef::Normal(d),
76 Self::Type(d) => TermDefinitionRef::Type(d),
77 }
78 }
79}
80
81pub type DefinitionParts<T, B> = (HashMap<Key, NormalTermDefinition<T, B>>, Option<TypeTermDefinition>);
83
84#[derive(Clone, PartialEq, Eq)]
86pub struct Definitions<T, B> {
87 normal: HashMap<Key, NormalTermDefinition<T, B>>,
88 type_: Option<TypeTermDefinition>,
89}
90
91impl<T, B> Default for Definitions<T, B> {
92 fn default() -> Self {
93 Self {
94 normal: HashMap::default(),
95 type_: None,
96 }
97 }
98}
99
100impl<T, B> Definitions<T, B> {
101 #[must_use]
103 pub fn into_parts(self) -> DefinitionParts<T, B> {
104 (self.normal, self.type_)
105 }
106
107 #[must_use]
109 pub fn len(&self) -> usize {
110 if self.type_.is_some() { self.normal.len() + 1 } else { self.normal.len() }
111 }
112
113 #[must_use]
115 pub fn is_empty(&self) -> bool {
116 self.type_.is_none() && self.normal.is_empty()
117 }
118
119 pub fn get<Q>(&self, term: &Q) -> Option<TermDefinitionRef<'_, T, B>>
121 where
122 Q: ?Sized + Hash + Eq,
123 Key: Borrow<Q>,
124 KeywordType: Borrow<Q>,
125 {
126 if KeywordType.borrow() == term {
127 self.type_.as_ref().map(TermDefinitionRef::Type)
128 } else {
129 self.normal.get(term).map(TermDefinitionRef::Normal)
130 }
131 }
132
133 pub fn get_normal<Q>(&self, term: &Q) -> Option<&NormalTermDefinition<T, B>>
135 where
136 Q: ?Sized + Hash + Eq,
137 Key: Borrow<Q>,
138 {
139 self.normal.get(term)
140 }
141
142 #[must_use]
144 pub fn get_type(&self) -> Option<&TypeTermDefinition> {
145 self.type_.as_ref()
146 }
147
148 pub fn contains_term<Q>(&self, term: &Q) -> bool
150 where
151 Q: ?Sized + Hash + Eq,
152 Key: Borrow<Q>,
153 KeywordType: Borrow<Q>,
154 {
155 if KeywordType.borrow() == term {
156 self.type_.is_some()
157 } else {
158 self.normal.contains_key(term)
159 }
160 }
161
162 pub fn insert(&mut self, binding: Binding<T, B>) -> Option<TermDefinition<T, B>> {
164 match binding {
165 Binding::Normal(key, definition) => self.insert_normal(key, definition).map(TermDefinition::Normal),
166 Binding::Type(definition) => self.insert_type(definition).map(TermDefinition::Type),
167 }
168 }
169
170 pub fn insert_normal(&mut self, term: Key, definition: NormalTermDefinition<T, B>) -> Option<NormalTermDefinition<T, B>> {
172 self.normal.insert(term, definition)
173 }
174
175 pub fn insert_type(&mut self, definition: TypeTermDefinition) -> Option<TypeTermDefinition> {
177 self.type_.replace(definition)
178 }
179
180 pub fn set_normal(&mut self, term: Key, definition: Option<NormalTermDefinition<T, B>>) -> Option<NormalTermDefinition<T, B>> {
182 match definition {
183 Some(d) => self.normal.insert(term, d),
184 None => self.normal.remove(&term),
185 }
186 }
187
188 pub fn set_type(&mut self, definition: Option<TypeTermDefinition>) -> Option<TypeTermDefinition> {
190 std::mem::replace(&mut self.type_, definition)
191 }
192
193 #[must_use]
195 pub fn iter(&self) -> Iter<'_, T, B> {
196 Iter {
197 type_: self.type_.as_ref(),
198 normal: self.normal.iter(),
199 }
200 }
201
202 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>) -> Definitions<U, C>
205 where
206 T: Clone,
207 B: Clone,
208 {
209 Definitions {
210 normal: self.normal.into_iter().map(|(key, d)| (key, d.map_ids(&mut map_iri, &mut map_id))).collect(),
211 type_: self.type_,
212 }
213 }
214}
215
216pub struct Iter<'a, T, B> {
218 type_: Option<&'a TypeTermDefinition>,
219 normal: hashbrown::hash_map::Iter<'a, Key, NormalTermDefinition<T, B>>,
220}
221
222impl<'a, T, B> Iterator for Iter<'a, T, B> {
223 type Item = BindingRef<'a, T, B>;
224
225 fn next(&mut self) -> Option<Self::Item> {
226 self.type_
227 .take()
228 .map(BindingRef::Type)
229 .or_else(|| self.normal.next().map(|(k, d)| BindingRef::Normal(k, d)))
230 }
231}
232
233impl<'a, T, B> IntoIterator for &'a Definitions<T, B> {
234 type Item = BindingRef<'a, T, B>;
235 type IntoIter = Iter<'a, T, B>;
236
237 fn into_iter(self) -> Self::IntoIter {
238 self.iter()
239 }
240}
241
242pub struct IntoIter<T, B> {
244 type_: Option<TypeTermDefinition>,
245 normal: hashbrown::hash_map::IntoIter<Key, NormalTermDefinition<T, B>>,
246}
247
248impl<T, B> Iterator for IntoIter<T, B> {
249 type Item = Binding<T, B>;
250
251 fn next(&mut self) -> Option<Self::Item> {
252 self.type_
253 .take()
254 .map(Binding::Type)
255 .or_else(|| self.normal.next().map(|(k, d)| Binding::Normal(k, d)))
256 }
257}
258
259impl<T, B> IntoIterator for Definitions<T, B> {
260 type Item = Binding<T, B>;
261 type IntoIter = IntoIter<T, B>;
262
263 fn into_iter(self) -> Self::IntoIter {
264 IntoIter {
265 type_: self.type_,
266 normal: self.normal.into_iter(),
267 }
268 }
269}
270
271#[derive(PartialEq, Eq, Clone)]
276pub struct TypeTermDefinition {
277 pub container: TypeContainer,
279
280 pub protected: bool,
282}
283
284impl Default for TypeTermDefinition {
285 fn default() -> Self {
286 Self {
287 container: TypeContainer::Set,
288 protected: false,
289 }
290 }
291}
292
293impl TypeTermDefinition {
294 #[must_use]
298 pub fn modulo_protected_field(&self) -> ModuloProtected<&Self> {
299 ModuloProtected(self)
300 }
301
302 #[must_use]
304 pub fn into_syntax_definition(self) -> jsonld_syntax::context::definition::Type {
305 jsonld_syntax::context::definition::Type {
306 container: self.container,
307 protected: if self.protected { Some(true) } else { None },
308 }
309 }
310}
311
312#[derive(PartialEq, Eq, Clone)]
314pub enum TermDefinition<T, B> {
315 Type(TypeTermDefinition),
317
318 Normal(NormalTermDefinition<T, B>),
320}
321
322impl<T, B> TermDefinition<T, B> {
323 pub fn as_ref(&self) -> TermDefinitionRef<'_, T, B> {
325 match self {
326 Self::Type(t) => TermDefinitionRef::Type(t),
327 Self::Normal(n) => TermDefinitionRef::Normal(n),
328 }
329 }
330
331 pub fn modulo_protected_field(&self) -> ModuloProtected<TermDefinitionRef<'_, T, B>> {
335 ModuloProtected(self.as_ref())
336 }
337
338 pub fn value(&self) -> Option<&Term<T, B>> {
341 match self {
342 Self::Type(_) => None,
343 Self::Normal(d) => d.value.as_deref(),
344 }
345 }
346
347 pub fn prefix(&self) -> bool {
349 match self {
350 Self::Type(_) => false,
351 Self::Normal(d) => d.prefix,
352 }
353 }
354
355 pub fn protected(&self) -> bool {
357 match self {
358 Self::Type(d) => d.protected,
359 Self::Normal(d) => d.protected,
360 }
361 }
362
363 pub fn reverse_property(&self) -> bool {
365 match self {
366 Self::Type(_) => false,
367 Self::Normal(d) => d.reverse_property,
368 }
369 }
370
371 pub fn base_url(&self) -> Option<&T> {
373 match self {
374 Self::Type(_) => None,
375 Self::Normal(d) => d.base_url.as_ref(),
376 }
377 }
378
379 pub fn context(&self) -> Option<&jsonld_syntax::context::Context> {
381 match self {
382 Self::Type(_) => None,
383 Self::Normal(d) => d.context.as_deref(),
384 }
385 }
386
387 pub fn container(&self) -> Container {
389 match self {
390 Self::Type(d) => d.container.into(),
391 Self::Normal(d) => d.container,
392 }
393 }
394
395 pub fn direction(&self) -> Option<Nullable<Direction>> {
397 match self {
398 Self::Type(_) => None,
399 Self::Normal(d) => d.direction,
400 }
401 }
402
403 pub fn index(&self) -> Option<&Index> {
405 match self {
406 Self::Type(_) => None,
407 Self::Normal(d) => d.index.as_ref(),
408 }
409 }
410
411 pub fn language(&self) -> Option<Nullable<&LenientLangTagBuf>> {
413 match self {
414 Self::Type(_) => None,
415 Self::Normal(d) => d.language.as_ref().map(Nullable::as_ref),
416 }
417 }
418
419 pub fn nest(&self) -> Option<&Nest> {
421 match self {
422 Self::Type(_) => None,
423 Self::Normal(d) => d.nest.as_ref(),
424 }
425 }
426
427 pub fn typ(&self) -> Option<&Type<T>> {
429 match self {
430 Self::Type(_) => None,
431 Self::Normal(d) => d.typ.as_ref(),
432 }
433 }
434}
435
436#[derive(PartialEq, Eq)]
438pub enum TermDefinitionRef<'a, T = IriBuf, B = BlankIdBuf> {
439 Type(&'a TypeTermDefinition),
441
442 Normal(&'a NormalTermDefinition<T, B>),
444}
445
446impl<'a, T, B> TermDefinitionRef<'a, T, B> {
447 #[must_use]
451 pub fn modulo_protected_field(&self) -> ModuloProtected<Self> {
452 ModuloProtected(*self)
453 }
454
455 #[must_use]
458 pub fn value(&self) -> Option<&'a Term<T, B>> {
459 match self {
460 Self::Type(_) => None,
461 Self::Normal(d) => d.value.as_deref(),
462 }
463 }
464
465 #[must_use]
468 pub fn value_arc(&self) -> Option<&'a Arc<Term<T, B>>> {
469 match self {
470 Self::Type(_) => None,
471 Self::Normal(d) => d.value.as_ref(),
472 }
473 }
474
475 #[must_use]
477 pub fn prefix(&self) -> bool {
478 match self {
479 Self::Type(_) => false,
480 Self::Normal(d) => d.prefix,
481 }
482 }
483
484 #[must_use]
486 pub fn protected(&self) -> bool {
487 match self {
488 Self::Type(d) => d.protected,
489 Self::Normal(d) => d.protected,
490 }
491 }
492
493 #[must_use]
495 pub fn reverse_property(&self) -> bool {
496 match self {
497 Self::Type(_) => false,
498 Self::Normal(d) => d.reverse_property,
499 }
500 }
501
502 #[must_use]
504 pub fn base_url(&self) -> Option<&'a T> {
505 match self {
506 Self::Type(_) => None,
507 Self::Normal(d) => d.base_url.as_ref(),
508 }
509 }
510
511 #[must_use]
513 pub fn context(&self) -> Option<&'a jsonld_syntax::context::Context> {
514 match self {
515 Self::Type(_) => None,
516 Self::Normal(d) => d.context.as_deref(),
517 }
518 }
519
520 #[must_use]
522 pub fn container(&self) -> Container {
523 match self {
524 Self::Type(d) => d.container.into(),
525 Self::Normal(d) => d.container,
526 }
527 }
528
529 #[must_use]
531 pub fn direction(&self) -> Option<Nullable<Direction>> {
532 match self {
533 Self::Type(_) => None,
534 Self::Normal(d) => d.direction,
535 }
536 }
537
538 #[must_use]
540 pub fn index(&self) -> Option<&'a Index> {
541 match self {
542 Self::Type(_) => None,
543 Self::Normal(d) => d.index.as_ref(),
544 }
545 }
546
547 pub fn language(&self) -> Option<Nullable<&'a LenientLangTagBuf>> {
549 match self {
550 Self::Type(_) => None,
551 Self::Normal(d) => d.language.as_ref().map(Nullable::as_ref),
552 }
553 }
554
555 #[must_use]
557 pub fn nest(&self) -> Option<&'a Nest> {
558 match self {
559 Self::Type(_) => None,
560 Self::Normal(d) => d.nest.as_ref(),
561 }
562 }
563
564 #[must_use]
566 pub fn typ(&self) -> Option<&'a Type<T>> {
567 match self {
568 Self::Type(_) => None,
569 Self::Normal(d) => d.typ.as_ref(),
570 }
571 }
572}
573
574impl<T, B> Clone for TermDefinitionRef<'_, T, B> {
575 fn clone(&self) -> Self {
576 *self
577 }
578}
579
580impl<T, B> Copy for TermDefinitionRef<'_, T, B> {}
581
582#[derive(PartialEq, Eq, Clone)]
583pub struct NormalTermDefinition<T = IriBuf, B = BlankIdBuf> {
585 pub value: Option<Arc<Term<T, B>>>,
592
593 pub prefix: bool,
595
596 pub protected: bool,
598
599 pub reverse_property: bool,
601
602 pub base_url: Option<T>,
604
605 pub context: Option<Box<jsonld_syntax::context::Context>>,
607
608 pub container: Container,
610
611 pub direction: Option<Nullable<Direction>>,
613
614 pub index: Option<Index>,
616
617 pub language: Option<Nullable<LenientLangTagBuf>>,
619
620 pub nest: Option<Nest>,
622
623 pub typ: Option<Type<T>>,
625}
626
627impl<T, B> NormalTermDefinition<T, B> {
628 pub fn modulo_protected_field(&self) -> ModuloProtected<&Self> {
632 ModuloProtected(self)
633 }
634
635 pub fn base_url(&self) -> Option<&T> {
637 self.base_url.as_ref()
638 }
639
640 pub fn value(&self) -> Option<&Term<T, B>> {
642 self.value.as_deref()
643 }
644
645 pub fn value_arc(&self) -> Option<&Arc<Term<T, B>>> {
647 self.value.as_ref()
648 }
649
650 pub fn into_syntax_definition(
656 self,
657 vocabulary: &impl Vocabulary<Iri = T, BlankId = B>,
658 ) -> Result<Nullable<jsonld_syntax::context::TermDefinition>, super::InvalidContextError>
659 where
660 T: Clone,
661 B: Clone,
662 {
663 use jsonld_syntax::context::term_definition::{Id, Type as SyntaxType, TypeKeyword};
664
665 fn term_into_id<T, B>(vocabulary: &impl Vocabulary<Iri = T, BlankId = B>, term: Term<T, B>) -> Nullable<Id> {
666 match term {
667 Term::Null => Nullable::Null,
668 Term::Keyword(k) => Nullable::Some(Id::Keyword(k)),
669 Term::Id(r) => Nullable::Some(Id::Term(r.with(vocabulary).to_string())),
670 }
671 }
672
673 fn term_into_key<T, B>(vocabulary: &impl Vocabulary<Iri = T, BlankId = B>, term: Term<T, B>) -> Result<Key, super::InvalidContextKey> {
674 match term {
675 Term::Null => Err(super::InvalidContextKey),
676 Term::Keyword(k) => Ok(k.to_string().into()),
677 Term::Id(r) => Ok(r.with(vocabulary).to_string().into()),
678 }
679 }
680
681 fn type_into_syntax<T>(vocabulary: &impl IriVocabulary<Iri = T>, ty: Type<T>) -> Result<SyntaxType, super::InvalidContextError> {
682 match ty {
683 Type::Id => Ok(SyntaxType::Keyword(TypeKeyword::Id)),
684 Type::Json => Ok(SyntaxType::Keyword(TypeKeyword::Json)),
685 Type::None => Ok(SyntaxType::Keyword(TypeKeyword::None)),
686 Type::Vocab => Ok(SyntaxType::Keyword(TypeKeyword::Vocab)),
687 Type::Iri(t) => match vocabulary.iri(&t) {
688 Some(iri) => Ok(SyntaxType::Term(iri.to_string())),
689 None => Err(super::InvalidContextError::UnresolvedIri),
690 },
691 }
692 }
693
694 fn unwrap_term<T: Clone, B: Clone>(arc: Arc<Term<T, B>>) -> Term<T, B> {
695 Arc::try_unwrap(arc).unwrap_or_else(|a| (*a).clone())
696 }
697
698 let (id, reverse) = if self.reverse_property {
699 let reverse = self.value.map(|t| term_into_key(vocabulary, unwrap_term(t))).transpose()?;
700 (None, reverse)
701 } else {
702 (self.value.map(|t| term_into_id(vocabulary, unwrap_term(t))), None)
703 };
704
705 let container = self.container.into_syntax();
706
707 let context = match self.context {
708 Some(e) => Some(Box::new(e.into_syntax(vocabulary)?)),
709 None => None,
710 };
711
712 Ok(jsonld_syntax::context::term_definition::Expanded {
713 id,
714 type_: self.typ.map(|t| type_into_syntax(vocabulary, t).map(Nullable::Some)).transpose()?,
715 context,
716 reverse,
717 index: self.index.clone(),
718 language: self.language,
719 direction: self.direction,
720 container: container.map(Nullable::Some),
721 nest: self.nest.clone(),
722 prefix: if self.prefix { Some(true) } else { None },
723 propagate: None,
724 protected: if self.protected { Some(true) } else { None },
725 }
726 .simplify())
727 }
728
729 fn map_ids<U, C>(self, mut map_iri: impl FnMut(T) -> U, map_id: impl FnOnce(Id<T, B>) -> Id<U, C>) -> NormalTermDefinition<U, C>
730 where
731 T: Clone,
732 B: Clone,
733 {
734 NormalTermDefinition {
735 value: self.value.map(|t| {
736 let term = Arc::try_unwrap(t).unwrap_or_else(|a| (*a).clone());
737 Arc::new(term.map_id(map_id))
738 }),
739 prefix: self.prefix,
740 protected: self.protected,
741 reverse_property: self.reverse_property,
742 base_url: self.base_url.map(&mut map_iri),
743 context: self.context,
744 container: self.container,
745 direction: self.direction,
746 index: self.index,
747 language: self.language,
748 nest: self.nest,
749 typ: self.typ.map(|t| t.map(map_iri)),
750 }
751 }
752}
753
754impl<T, B> Default for NormalTermDefinition<T, B> {
755 fn default() -> NormalTermDefinition<T, B> {
756 NormalTermDefinition {
757 value: None,
758 prefix: false,
759 protected: false,
760 reverse_property: false,
761 base_url: None,
762 typ: None,
763 language: None,
764 direction: None,
765 context: None,
766 nest: None,
767 index: None,
768 container: Container::new(),
769 }
770 }
771}
772
773pub struct ModuloProtected<T>(T);
775
776impl<'b, T: PartialEq, B: PartialEq> PartialEq<ModuloProtected<&'b NormalTermDefinition<T, B>>> for ModuloProtected<&NormalTermDefinition<T, B>> {
777 fn eq(&self, other: &ModuloProtected<&'b NormalTermDefinition<T, B>>) -> bool {
778 self.0.prefix == other.0.prefix
780 && self.0.reverse_property == other.0.reverse_property
781 && self.0.language == other.0.language
782 && self.0.direction == other.0.direction
783 && self.0.nest == other.0.nest
784 && self.0.index == other.0.index
785 && self.0.container == other.0.container
786 && self.0.base_url == other.0.base_url
787 && self.0.value == other.0.value
788 && self.0.typ == other.0.typ
789 && self.0.context == other.0.context
790 }
791}
792
793impl<T: Eq, B: Eq> Eq for ModuloProtected<&NormalTermDefinition<T, B>> {}
794
795impl<'b> PartialEq<ModuloProtected<&'b TypeTermDefinition>> for ModuloProtected<&TypeTermDefinition> {
796 fn eq(&self, other: &ModuloProtected<&'b TypeTermDefinition>) -> bool {
797 self.0.container == other.0.container
799 }
800}
801
802impl Eq for ModuloProtected<&TypeTermDefinition> {}
803
804impl<'b, T: PartialEq, B: PartialEq> PartialEq<ModuloProtected<TermDefinitionRef<'b, T, B>>> for ModuloProtected<TermDefinitionRef<'_, T, B>> {
805 fn eq(&self, other: &ModuloProtected<TermDefinitionRef<'b, T, B>>) -> bool {
806 self.0.prefix() == other.0.prefix()
808 && self.0.reverse_property() == other.0.reverse_property()
809 && self.0.language() == other.0.language()
810 && self.0.direction() == other.0.direction()
811 && self.0.nest() == other.0.nest()
812 && self.0.index() == other.0.index()
813 && self.0.container() == other.0.container()
814 && self.0.base_url() == other.0.base_url()
815 && self.0.value() == other.0.value()
816 && self.0.typ() == other.0.typ()
817 && self.0.context() == other.0.context()
818 }
819}
820
821impl<T: Eq, B: Eq> Eq for ModuloProtected<TermDefinitionRef<'_, T, B>> {}