1use super::{IntoSyntax, Nest};
2use crate::{Container, Direction, LenientLangTagBuf, Nullable, Term, Type};
3use contextual::WithContext;
4use iref::IriBuf;
5use json_ld_syntax::{
6 context::{
7 definition::{Key, TypeContainer},
8 term_definition::Index,
9 },
10 KeywordType,
11};
12use rdf_types::{vocabulary::IriVocabulary, BlankIdBuf, Id, Vocabulary};
13use std::collections::HashMap;
14use std::hash::Hash;
15use std::{borrow::Borrow, fmt};
16
17pub enum Binding<T = IriBuf, B = BlankIdBuf> {
19 Normal(Key, NormalTermDefinition<T, B>),
21
22 Type(TypeTermDefinition),
24}
25
26pub enum BindingRef<'a, T, B> {
28 Normal(&'a Key, &'a NormalTermDefinition<T, B>),
30
31 Type(&'a TypeTermDefinition),
33}
34
35pub enum BindingTerm<'a> {
36 Normal(&'a Key),
37 Type,
38}
39
40impl<'a> BindingTerm<'a> {
41 pub fn as_str(&self) -> &'a str {
42 match self {
43 Self::Normal(key) => key.as_str(),
44 Self::Type => "@type",
45 }
46 }
47}
48
49impl<'a> fmt::Display for BindingTerm<'a> {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 self.as_str().fmt(f)
52 }
53}
54
55impl<'a, T, B> BindingRef<'a, T, B> {
56 pub fn term(&self) -> BindingTerm<'a> {
58 match self {
59 Self::Normal(key, _) => BindingTerm::Normal(key),
60 Self::Type(_) => BindingTerm::Type,
61 }
62 }
63
64 pub fn definition(&self) -> TermDefinitionRef<'a, T, B> {
66 match self {
67 Self::Normal(_, d) => TermDefinitionRef::Normal(d),
68 Self::Type(d) => TermDefinitionRef::Type(d),
69 }
70 }
71}
72
73#[derive(Clone)]
75pub struct Definitions<T, B> {
76 normal: HashMap<Key, NormalTermDefinition<T, B>>,
77 type_: Option<TypeTermDefinition>,
78}
79
80impl<T, B> Default for Definitions<T, B> {
81 fn default() -> Self {
82 Self {
83 normal: HashMap::new(),
84 type_: None,
85 }
86 }
87}
88
89impl<T, B> Definitions<T, B> {
90 #[allow(clippy::type_complexity)]
91 pub fn into_parts(
92 self,
93 ) -> (
94 HashMap<Key, NormalTermDefinition<T, B>>,
95 Option<TypeTermDefinition>,
96 ) {
97 (self.normal, self.type_)
98 }
99
100 pub fn len(&self) -> usize {
102 if self.type_.is_some() {
103 self.normal.len() + 1
104 } else {
105 self.normal.len()
106 }
107 }
108
109 pub fn is_empty(&self) -> bool {
111 self.type_.is_none() && self.normal.is_empty()
112 }
113
114 pub fn get<Q>(&self, term: &Q) -> Option<TermDefinitionRef<T, B>>
116 where
117 Q: ?Sized + Hash + Eq,
118 Key: Borrow<Q>,
119 KeywordType: Borrow<Q>,
120 {
121 if KeywordType.borrow() == term {
122 self.type_.as_ref().map(TermDefinitionRef::Type)
123 } else {
124 self.normal.get(term).map(TermDefinitionRef::Normal)
125 }
126 }
127
128 pub fn get_normal<Q>(&self, term: &Q) -> Option<&NormalTermDefinition<T, B>>
130 where
131 Q: ?Sized + Hash + Eq,
132 Key: Borrow<Q>,
133 {
134 self.normal.get(term)
135 }
136
137 pub fn get_type(&self) -> Option<&TypeTermDefinition> {
139 self.type_.as_ref()
140 }
141
142 pub fn contains_term<Q>(&self, term: &Q) -> bool
143 where
144 Q: ?Sized + Hash + Eq,
145 Key: Borrow<Q>,
146 KeywordType: Borrow<Q>,
147 {
148 if KeywordType.borrow() == term {
149 self.type_.is_some()
150 } else {
151 self.normal.contains_key(term)
152 }
153 }
154
155 pub fn insert(&mut self, binding: Binding<T, B>) -> Option<TermDefinition<T, B>> {
157 match binding {
158 Binding::Normal(key, definition) => self
159 .insert_normal(key, definition)
160 .map(TermDefinition::Normal),
161 Binding::Type(definition) => self.insert_type(definition).map(TermDefinition::Type),
162 }
163 }
164
165 pub fn insert_normal(
167 &mut self,
168 term: Key,
169 definition: NormalTermDefinition<T, B>,
170 ) -> Option<NormalTermDefinition<T, B>> {
171 self.normal.insert(term, definition)
172 }
173
174 pub fn insert_type(&mut self, definition: TypeTermDefinition) -> Option<TypeTermDefinition> {
176 std::mem::replace(&mut self.type_, Some(definition))
177 }
178
179 pub fn set_normal(
181 &mut self,
182 term: Key,
183 definition: Option<NormalTermDefinition<T, B>>,
184 ) -> Option<NormalTermDefinition<T, B>> {
185 match definition {
186 Some(d) => self.normal.insert(term, d),
187 None => self.normal.remove(&term),
188 }
189 }
190
191 pub fn set_type(
193 &mut self,
194 definition: Option<TypeTermDefinition>,
195 ) -> Option<TypeTermDefinition> {
196 std::mem::replace(&mut self.type_, definition)
197 }
198
199 pub fn iter(&self) -> Iter<T, B> {
201 Iter {
202 type_: self.type_.as_ref(),
203 normal: self.normal.iter(),
204 }
205 }
206
207 pub fn map_ids<U, C>(
208 self,
209 mut map_iri: impl FnMut(T) -> U,
210 mut map_id: impl FnMut(Id<T, B>) -> Id<U, C>,
211 ) -> Definitions<U, C> {
212 Definitions {
213 normal: self
214 .normal
215 .into_iter()
216 .map(|(key, d)| (key, d.map_ids(&mut map_iri, &mut map_id)))
217 .collect(),
218 type_: self.type_,
219 }
220 }
221}
222
223pub struct Iter<'a, T, B> {
224 type_: Option<&'a TypeTermDefinition>,
225 normal: std::collections::hash_map::Iter<'a, Key, NormalTermDefinition<T, B>>,
226}
227
228impl<'a, T, B> Iterator for Iter<'a, T, B> {
229 type Item = BindingRef<'a, T, B>;
230
231 fn next(&mut self) -> Option<Self::Item> {
232 self.type_
233 .take()
234 .map(BindingRef::Type)
235 .or_else(|| self.normal.next().map(|(k, d)| BindingRef::Normal(k, d)))
236 }
237}
238
239impl<'a, T, B> IntoIterator for &'a Definitions<T, B> {
240 type Item = BindingRef<'a, T, B>;
241 type IntoIter = Iter<'a, T, B>;
242
243 fn into_iter(self) -> Self::IntoIter {
244 self.iter()
245 }
246}
247
248pub struct IntoIter<T, B> {
249 type_: Option<TypeTermDefinition>,
250 normal: std::collections::hash_map::IntoIter<Key, NormalTermDefinition<T, B>>,
251}
252
253impl<T, B> Iterator for IntoIter<T, B> {
254 type Item = Binding<T, B>;
255
256 fn next(&mut self) -> Option<Self::Item> {
257 self.type_
258 .take()
259 .map(Binding::Type)
260 .or_else(|| self.normal.next().map(|(k, d)| Binding::Normal(k, d)))
261 }
262}
263
264impl<T, B> IntoIterator for Definitions<T, B> {
265 type Item = Binding<T, B>;
266 type IntoIter = IntoIter<T, B>;
267
268 fn into_iter(self) -> Self::IntoIter {
269 IntoIter {
270 type_: self.type_,
271 normal: self.normal.into_iter(),
272 }
273 }
274}
275
276#[derive(PartialEq, Eq, Clone)]
281pub struct TypeTermDefinition {
282 pub container: TypeContainer,
284
285 pub protected: bool,
287}
288
289impl Default for TypeTermDefinition {
290 fn default() -> Self {
291 Self {
292 container: TypeContainer::Set,
293 protected: false,
294 }
295 }
296}
297
298impl TypeTermDefinition {
299 pub fn modulo_protected_field(&self) -> ModuloProtected<&Self> {
300 ModuloProtected(self)
301 }
302
303 pub fn into_syntax_definition(self) -> json_ld_syntax::context::definition::Type {
304 json_ld_syntax::context::definition::Type {
305 container: self.container,
306 protected: if self.protected { Some(true) } else { None },
307 }
308 }
309}
310
311#[derive(PartialEq, Eq, Clone)]
313pub enum TermDefinition<T, B> {
314 Type(TypeTermDefinition),
316
317 Normal(NormalTermDefinition<T, B>),
319}
320
321impl<T, B> TermDefinition<T, B> {
322 pub fn as_ref(&self) -> TermDefinitionRef<T, B> {
323 match self {
324 Self::Type(t) => TermDefinitionRef::Type(t),
325 Self::Normal(n) => TermDefinitionRef::Normal(n),
326 }
327 }
328
329 pub fn modulo_protected_field(&self) -> ModuloProtected<TermDefinitionRef<T, B>> {
330 ModuloProtected(self.as_ref())
331 }
332
333 pub fn value(&self) -> Option<&Term<T, B>> {
334 match self {
335 Self::Type(_) => None,
336 Self::Normal(d) => d.value.as_ref(),
337 }
338 }
339
340 pub fn prefix(&self) -> bool {
341 match self {
342 Self::Type(_) => false,
343 Self::Normal(d) => d.prefix,
344 }
345 }
346
347 pub fn protected(&self) -> bool {
348 match self {
349 Self::Type(d) => d.protected,
350 Self::Normal(d) => d.protected,
351 }
352 }
353
354 pub fn reverse_property(&self) -> bool {
355 match self {
356 Self::Type(_) => false,
357 Self::Normal(d) => d.reverse_property,
358 }
359 }
360
361 pub fn base_url(&self) -> Option<&T> {
362 match self {
363 Self::Type(_) => None,
364 Self::Normal(d) => d.base_url.as_ref(),
365 }
366 }
367
368 pub fn context(&self) -> Option<&json_ld_syntax::context::Context> {
369 match self {
370 Self::Type(_) => None,
371 Self::Normal(d) => d.context.as_deref(),
372 }
373 }
374
375 pub fn container(&self) -> Container {
376 match self {
377 Self::Type(d) => d.container.into(),
378 Self::Normal(d) => d.container,
379 }
380 }
381
382 pub fn direction(&self) -> Option<Nullable<Direction>> {
383 match self {
384 Self::Type(_) => None,
385 Self::Normal(d) => d.direction,
386 }
387 }
388
389 pub fn index(&self) -> Option<&Index> {
390 match self {
391 Self::Type(_) => None,
392 Self::Normal(d) => d.index.as_ref(),
393 }
394 }
395
396 pub fn language(&self) -> Option<Nullable<&LenientLangTagBuf>> {
397 match self {
398 Self::Type(_) => None,
399 Self::Normal(d) => d.language.as_ref().map(Nullable::as_ref),
400 }
401 }
402
403 pub fn nest(&self) -> Option<&Nest> {
404 match self {
405 Self::Type(_) => None,
406 Self::Normal(d) => d.nest.as_ref(),
407 }
408 }
409
410 pub fn typ(&self) -> Option<&Type<T>> {
411 match self {
412 Self::Type(_) => None,
413 Self::Normal(d) => d.typ.as_ref(),
414 }
415 }
416}
417
418#[derive(PartialEq, Eq)]
420pub enum TermDefinitionRef<'a, T = IriBuf, B = BlankIdBuf> {
421 Type(&'a TypeTermDefinition),
423
424 Normal(&'a NormalTermDefinition<T, B>),
426}
427
428impl<'a, T, B> TermDefinitionRef<'a, T, B> {
429 pub fn modulo_protected_field(&self) -> ModuloProtected<Self> {
430 ModuloProtected(*self)
431 }
432
433 pub fn value(&self) -> Option<&'a Term<T, B>> {
434 match self {
435 Self::Type(_) => None,
436 Self::Normal(d) => d.value.as_ref(),
437 }
438 }
439
440 pub fn prefix(&self) -> bool {
441 match self {
442 Self::Type(_) => false,
443 Self::Normal(d) => d.prefix,
444 }
445 }
446
447 pub fn protected(&self) -> bool {
448 match self {
449 Self::Type(d) => d.protected,
450 Self::Normal(d) => d.protected,
451 }
452 }
453
454 pub fn reverse_property(&self) -> bool {
455 match self {
456 Self::Type(_) => false,
457 Self::Normal(d) => d.reverse_property,
458 }
459 }
460
461 pub fn base_url(&self) -> Option<&'a T> {
462 match self {
463 Self::Type(_) => None,
464 Self::Normal(d) => d.base_url.as_ref(),
465 }
466 }
467
468 pub fn context(&self) -> Option<&'a json_ld_syntax::context::Context> {
469 match self {
470 Self::Type(_) => None,
471 Self::Normal(d) => d.context.as_deref(),
472 }
473 }
474
475 pub fn container(&self) -> Container {
476 match self {
477 Self::Type(d) => d.container.into(),
478 Self::Normal(d) => d.container,
479 }
480 }
481
482 pub fn direction(&self) -> Option<Nullable<Direction>> {
483 match self {
484 Self::Type(_) => None,
485 Self::Normal(d) => d.direction,
486 }
487 }
488
489 pub fn index(&self) -> Option<&'a Index> {
490 match self {
491 Self::Type(_) => None,
492 Self::Normal(d) => d.index.as_ref(),
493 }
494 }
495
496 pub fn language(&self) -> Option<Nullable<&'a LenientLangTagBuf>> {
497 match self {
498 Self::Type(_) => None,
499 Self::Normal(d) => d.language.as_ref().map(Nullable::as_ref),
500 }
501 }
502
503 pub fn nest(&self) -> Option<&'a Nest> {
504 match self {
505 Self::Type(_) => None,
506 Self::Normal(d) => d.nest.as_ref(),
507 }
508 }
509
510 pub fn typ(&self) -> Option<&'a Type<T>> {
511 match self {
512 Self::Type(_) => None,
513 Self::Normal(d) => d.typ.as_ref(),
514 }
515 }
516}
517
518impl<'a, T, B> Clone for TermDefinitionRef<'a, T, B> {
519 fn clone(&self) -> Self {
520 *self
521 }
522}
523
524impl<'a, T, B> Copy for TermDefinitionRef<'a, T, B> {}
525
526#[derive(PartialEq, Eq, Clone)]
528pub struct NormalTermDefinition<T = IriBuf, B = BlankIdBuf> {
529 pub value: Option<Term<T, B>>,
531
532 pub prefix: bool,
534
535 pub protected: bool,
537
538 pub reverse_property: bool,
540
541 pub base_url: Option<T>,
543
544 pub context: Option<Box<json_ld_syntax::context::Context>>,
546
547 pub container: Container,
549
550 pub direction: Option<Nullable<Direction>>,
552
553 pub index: Option<Index>,
555
556 pub language: Option<Nullable<LenientLangTagBuf>>,
558
559 pub nest: Option<Nest>,
561
562 pub typ: Option<Type<T>>,
564}
565
566impl<T, B> NormalTermDefinition<T, B> {
567 pub fn modulo_protected_field(&self) -> ModuloProtected<&Self> {
568 ModuloProtected(self)
569 }
570
571 pub fn base_url(&self) -> Option<&T> {
572 self.base_url.as_ref()
573 }
574
575 pub fn into_syntax_definition(
576 self,
577 vocabulary: &impl Vocabulary<Iri = T, BlankId = B>,
578 ) -> Nullable<json_ld_syntax::context::TermDefinition> {
579 use json_ld_syntax::context::term_definition::{Id, Type as SyntaxType, TypeKeyword};
580
581 fn term_into_id<T, B>(
582 vocabulary: &impl Vocabulary<Iri = T, BlankId = B>,
583 term: Term<T, B>,
584 ) -> Nullable<Id> {
585 match term {
586 Term::Null => Nullable::Null,
587 Term::Keyword(k) => Nullable::Some(Id::Keyword(k)),
588 Term::Id(r) => Nullable::Some(Id::Term(r.with(vocabulary).to_string())),
589 }
590 }
591
592 fn term_into_key<T, B>(
593 vocabulary: &impl Vocabulary<Iri = T, BlankId = B>,
594 term: Term<T, B>,
595 ) -> Key {
596 match term {
597 Term::Null => panic!("invalid key"),
598 Term::Keyword(k) => k.to_string().into(),
599 Term::Id(r) => r.with(vocabulary).to_string().into(),
600 }
601 }
602
603 fn type_into_syntax<T>(
604 vocabulary: &impl IriVocabulary<Iri = T>,
605 ty: Type<T>,
606 ) -> SyntaxType {
607 match ty {
608 Type::Id => SyntaxType::Keyword(TypeKeyword::Id),
609 Type::Json => SyntaxType::Keyword(TypeKeyword::Json),
610 Type::None => SyntaxType::Keyword(TypeKeyword::None),
611 Type::Vocab => SyntaxType::Keyword(TypeKeyword::Vocab),
612 Type::Iri(t) => SyntaxType::Term(vocabulary.iri(&t).unwrap().to_string()),
613 }
614 }
615
616 let (id, reverse) = if self.reverse_property {
617 (None, self.value.map(|t| term_into_key(vocabulary, t)))
618 } else {
619 (self.value.map(|t| term_into_id(vocabulary, t)), None)
620 };
621
622 let container = self.container.into_syntax();
623
624 json_ld_syntax::context::term_definition::Expanded {
625 id,
626 type_: self
627 .typ
628 .map(|t| Nullable::Some(type_into_syntax(vocabulary, t))),
629 context: self.context.map(|e| Box::new(e.into_syntax(vocabulary))),
630 reverse,
631 index: self.index.clone(),
632 language: self.language,
633 direction: self.direction,
634 container: container.map(Nullable::Some),
635 nest: self.nest.clone(),
636 prefix: if self.prefix { Some(true) } else { None },
637 propagate: None,
638 protected: if self.protected { Some(true) } else { None },
639 }
640 .simplify()
641 }
642
643 fn map_ids<U, C>(
644 self,
645 mut map_iri: impl FnMut(T) -> U,
646 map_id: impl FnOnce(Id<T, B>) -> Id<U, C>,
647 ) -> NormalTermDefinition<U, C> {
648 NormalTermDefinition {
649 value: self.value.map(|t| t.map_id(map_id)),
650 prefix: self.prefix,
651 protected: self.protected,
652 reverse_property: self.reverse_property,
653 base_url: self.base_url.map(&mut map_iri),
654 context: self.context,
655 container: self.container,
656 direction: self.direction,
657 index: self.index,
658 language: self.language,
659 nest: self.nest,
660 typ: self.typ.map(|t| t.map(map_iri)),
661 }
662 }
663}
664
665impl<T, B> Default for NormalTermDefinition<T, B> {
666 fn default() -> NormalTermDefinition<T, B> {
667 NormalTermDefinition {
668 value: None,
669 prefix: false,
670 protected: false,
671 reverse_property: false,
672 base_url: None,
673 typ: None,
674 language: None,
675 direction: None,
676 context: None,
677 nest: None,
678 index: None,
679 container: Container::new(),
680 }
681 }
682}
683
684pub struct ModuloProtected<T>(T);
686
687impl<'a, 'b, T: PartialEq, B: PartialEq> PartialEq<ModuloProtected<&'b NormalTermDefinition<T, B>>>
688 for ModuloProtected<&'a NormalTermDefinition<T, B>>
689{
690 fn eq(&self, other: &ModuloProtected<&'b NormalTermDefinition<T, B>>) -> bool {
691 self.0.prefix == other.0.prefix
693 && self.0.reverse_property == other.0.reverse_property
694 && self.0.language == other.0.language
695 && self.0.direction == other.0.direction
696 && self.0.nest == other.0.nest
697 && self.0.index == other.0.index
698 && self.0.container == other.0.container
699 && self.0.base_url == other.0.base_url
700 && self.0.value == other.0.value
701 && self.0.typ == other.0.typ
702 && self.0.context == other.0.context
703 }
704}
705
706impl<'a, T: Eq, B: Eq> Eq for ModuloProtected<&'a NormalTermDefinition<T, B>> {}
707
708impl<'a, 'b> PartialEq<ModuloProtected<&'b TypeTermDefinition>>
709 for ModuloProtected<&'a TypeTermDefinition>
710{
711 fn eq(&self, other: &ModuloProtected<&'b TypeTermDefinition>) -> bool {
712 self.0.container == other.0.container
714 }
715}
716
717impl<'a> Eq for ModuloProtected<&'a TypeTermDefinition> {}
718
719impl<'a, 'b, T: PartialEq, B: PartialEq> PartialEq<ModuloProtected<TermDefinitionRef<'b, T, B>>>
720 for ModuloProtected<TermDefinitionRef<'a, T, B>>
721{
722 fn eq(&self, other: &ModuloProtected<TermDefinitionRef<'b, T, B>>) -> bool {
723 self.0.prefix() == other.0.prefix()
725 && self.0.reverse_property() == other.0.reverse_property()
726 && self.0.language() == other.0.language()
727 && self.0.direction() == other.0.direction()
728 && self.0.nest() == other.0.nest()
729 && self.0.index() == other.0.index()
730 && self.0.container() == other.0.container()
731 && self.0.base_url() == other.0.base_url()
732 && self.0.value() == other.0.value()
733 && self.0.typ() == other.0.typ()
734 && self.0.context() == other.0.context()
735 }
736}
737
738impl<'a, T: Eq, B: Eq> Eq for ModuloProtected<TermDefinitionRef<'a, T, B>> {}