json_ld_context_processing_next/algorithm/
merged.rs1use iref::IriRef;
2use json_ld_syntax_next as syntax;
3use syntax::Nullable;
4
5pub struct Merged<'a> {
6 base: &'a syntax::context::Definition,
7 imported: Option<syntax::context::Context>,
8}
9
10impl<'a> Merged<'a> {
11 pub fn new(
12 base: &'a syntax::context::Definition,
13 imported: Option<syntax::context::Context>,
14 ) -> Self {
15 Self { base, imported }
16 }
17
18 pub fn imported(&self) -> Option<&syntax::context::Definition> {
19 self.imported.as_ref().and_then(|imported| match imported {
20 syntax::context::Context::One(syntax::ContextEntry::Definition(import_context)) => {
21 Some(import_context)
22 }
23 _ => None,
24 })
25 }
26
27 pub fn base(&self) -> Option<syntax::Nullable<&IriRef>> {
28 self.base
29 .base
30 .as_ref()
31 .or_else(|| self.imported().and_then(|i| i.base.as_ref()))
32 .map(Nullable::as_deref)
33 }
34
35 pub fn vocab(&self) -> Option<syntax::Nullable<&syntax::context::definition::Vocab>> {
36 self.base
37 .vocab
38 .as_ref()
39 .or_else(|| self.imported().and_then(|i| i.vocab.as_ref()))
40 .map(Nullable::as_ref)
41 }
42
43 pub fn language(&self) -> Option<syntax::Nullable<&syntax::LenientLangTagBuf>> {
44 self.base
45 .language
46 .as_ref()
47 .or_else(|| self.imported().and_then(|i| i.language.as_ref()))
48 .map(Nullable::as_ref)
49 }
50
51 pub fn direction(&self) -> Option<syntax::Nullable<syntax::Direction>> {
52 self.base
53 .direction
54 .or_else(|| self.imported().and_then(|i| i.direction))
55 }
56
57 pub fn protected(&self) -> Option<bool> {
58 self.base
59 .protected
60 .or_else(|| self.imported().and_then(|i| i.protected))
61 }
62
63 pub fn type_(&self) -> Option<syntax::context::definition::Type> {
64 self.base
65 .type_
66 .or_else(|| self.imported().and_then(|i| i.type_))
67 }
68
69 pub fn bindings(&self) -> MergedBindings {
70 MergedBindings {
71 base: self.base,
72 base_bindings: self.base.bindings.iter(),
73 imported_bindings: self.imported().map(|i| i.bindings.iter()),
74 }
75 }
76
77 pub fn get(
78 &self,
79 key: &syntax::context::definition::KeyOrKeyword,
80 ) -> Option<syntax::context::definition::EntryValueRef> {
81 self.base
82 .get(key)
83 .or_else(|| self.imported().and_then(|i| i.get(key)))
84 }
88}
89
90impl<'a> From<&'a syntax::context::Definition> for Merged<'a> {
91 fn from(base: &'a syntax::context::Definition) -> Self {
92 Self {
93 base,
94 imported: None,
95 }
96 }
97}
98
99type BindingRef<'a> = (
135 &'a syntax::context::definition::Key,
136 Nullable<&'a syntax::context::TermDefinition>,
137);
138
139pub struct MergedBindings<'a> {
140 base: &'a syntax::context::Definition,
141 base_bindings: syntax::context::definition::BindingsIter<'a>,
142 imported_bindings: Option<syntax::context::definition::BindingsIter<'a>>,
143}
144
145impl<'a> Iterator for MergedBindings<'a> {
146 type Item = BindingRef<'a>;
147
148 fn next(&mut self) -> Option<Self::Item> {
149 match &mut self.imported_bindings {
150 Some(imported_bindings) => {
151 for (key_ref, def) in imported_bindings {
152 let key = key_ref.to_owned();
153 if self.base.get_binding(&key).is_none() {
154 return Some((key_ref, def));
155 }
156 }
157
158 self.base_bindings.next()
159 }
160 None => self.base_bindings.next(),
161 }
162 }
163}