json_ld_context_processing_next/algorithm/
merged.rs

1use 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		// self.imported()
85		// 	.and_then(|i| i.get(key))
86		// 	.or_else(|| self.base.get(key))
87	}
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
99// #[derive(Default)]
100// pub struct StaticMergedBindings {
101// 	base_offset: usize,
102// 	imported_offset: usize
103// }
104
105// impl StaticMergedBindings {
106// 	pub fn next<'a>(
107// 		&mut self,
108// 		context: &Merged<'a>
109// 	) -> Option<BindingRef<'a>> {
110// 		match context.base.bindings.get_entry(self.base_offset) {
111// 			Some(entry) => {
112// 				self.base_offset += 1;
113// 				Some(entry)
114// 			},
115// 			None => {
116// 				match context.imported() {
117// 					Some(imported) => {
118// 						while let Some(entry) = imported.bindings.get_entry(self.imported_offset) {
119// 							self.imported_offset += 1;
120// 							if context.base.get_binding(entry.0).is_none() {
121// 								return Some(entry)
122// 							}
123// 						}
124
125// 						None
126// 					},
127// 					None => None
128// 				}
129// 			}
130// 		}
131// 	}
132// }
133
134type 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}