json_ld/core/context/
mod.rs1mod container;
3mod definition;
4mod embed;
5pub mod inverse;
6
7pub use container::JsonLdContainer;
8use langtag::{LangTag, LangTagBuf};
9
10use crate::syntax::context::JsonLdContextTerm;
11use crate::syntax::{JsonLdContext, JsonLdKeywordType};
12use crate::{JsonLdDirection, JsonLdLenient, JsonLdTerm};
13use rdf_syntax::{Iri, IriBuf};
14use std::borrow::{Borrow, Cow};
15use std::hash::Hash;
16use std::ops::{Deref, DerefMut};
17use std::sync::OnceLock;
18
19pub use definition::*;
20pub use embed::*;
21pub use inverse::InverseJsonLdContext;
22
23pub struct JsonLdProcessedContext<'a> {
31 unprocessed: Cow<'a, JsonLdContext>,
32 raw: RawJsonLdProcessedContext,
33}
34
35impl<'a> JsonLdProcessedContext<'a> {
36 pub fn new(unprocessed: Cow<'a, JsonLdContext>, raw: RawJsonLdProcessedContext) -> Self {
37 Self { unprocessed, raw }
38 }
39
40 pub fn unprocessed(&self) -> &JsonLdContext {
41 &self.unprocessed
42 }
43
44 pub fn as_raw(&self) -> &RawJsonLdProcessedContext {
45 &self.raw
46 }
47
48 pub fn into_raw(self) -> RawJsonLdProcessedContext {
49 self.raw
50 }
51
52 pub fn into_owned(self) -> JsonLdProcessedContext<'static> {
53 JsonLdProcessedContext {
54 unprocessed: Cow::Owned(self.unprocessed.into_owned()),
55 raw: self.raw,
56 }
57 }
58}
59
60impl Deref for JsonLdProcessedContext<'_> {
61 type Target = RawJsonLdProcessedContext;
62
63 fn deref(&self) -> &Self::Target {
64 &self.raw
65 }
66}
67
68impl DerefMut for JsonLdProcessedContext<'_> {
69 fn deref_mut(&mut self) -> &mut Self::Target {
70 &mut self.raw
71 }
72}
73
74#[derive(Default)]
82pub struct RawJsonLdProcessedContext {
83 original_base_url: Option<IriBuf>,
84 base_iri: Option<IriBuf>,
85 vocabulary: Option<JsonLdTerm>,
86 default_language: Option<JsonLdLenient<LangTagBuf>>,
87 default_base_direction: Option<JsonLdDirection>,
88 previous_context: Option<Box<Self>>,
89 definitions: JsonLdDefinitions,
90 inverse: OnceLock<InverseJsonLdContext>,
91}
92
93pub type DefinitionEntryRef<'a> = (&'a JsonLdContextTerm, &'a JsonLdProcessedTermDefinition);
94
95impl RawJsonLdProcessedContext {
96 pub fn new(base_iri: Option<IriBuf>) -> Self {
98 Self {
99 original_base_url: base_iri.clone(),
100 base_iri,
101 vocabulary: None,
102 default_language: None,
103 default_base_direction: None,
104 previous_context: None,
105 definitions: JsonLdDefinitions::default(),
106 inverse: OnceLock::default(),
107 }
108 }
109
110 pub fn get<Q>(&self, term: &Q) -> Option<JsonLdProcessedTermDefinitionRef<'_>>
112 where
113 JsonLdContextTerm: Borrow<Q>,
114 JsonLdKeywordType: Borrow<Q>,
115 Q: ?Sized + Hash + Eq,
116 {
117 self.definitions.get(term)
118 }
119
120 pub fn get_normal<Q>(&self, term: &Q) -> Option<&JsonLdProcessedNormalTermDefinition>
122 where
123 JsonLdContextTerm: Borrow<Q>,
124 Q: ?Sized + Hash + Eq,
125 {
126 self.definitions.get_normal(term)
127 }
128
129 pub fn get_type(&self) -> Option<&JsonLdProcessedTypeTermDefinition> {
131 self.definitions.get_type()
132 }
133
134 pub fn contains_term<Q>(&self, term: &Q) -> bool
136 where
137 JsonLdContextTerm: Borrow<Q>,
138 JsonLdKeywordType: Borrow<Q>,
139 Q: ?Sized + Hash + Eq,
140 {
141 self.definitions.contains_term(term)
142 }
143
144 pub fn original_base_url(&self) -> Option<&Iri> {
146 self.original_base_url.as_deref()
147 }
148
149 pub fn base_iri(&self) -> Option<&Iri> {
151 self.base_iri.as_deref()
152 }
153
154 pub fn vocabulary(&self) -> Option<&JsonLdTerm> {
156 match &self.vocabulary {
157 Some(v) => Some(v),
158 None => None,
159 }
160 }
161
162 pub fn default_language(&self) -> Option<JsonLdLenient<&LangTag>> {
164 self.default_language.as_ref().map(|tag| tag.as_deref())
165 }
166
167 pub fn default_base_direction(&self) -> Option<JsonLdDirection> {
169 self.default_base_direction
170 }
171
172 pub fn previous_context(&self) -> Option<&Self> {
174 match &self.previous_context {
175 Some(c) => Some(c),
176 None => None,
177 }
178 }
179
180 pub fn len(&self) -> usize {
182 self.definitions.len()
183 }
184
185 pub fn is_empty(&self) -> bool {
187 self.definitions.is_empty()
188 }
189
190 pub fn definitions(&self) -> &JsonLdDefinitions {
192 &self.definitions
193 }
194
195 pub fn has_protected_items(&self) -> bool {
197 for binding in self.definitions() {
198 if binding.definition().protected() {
199 return true;
200 }
201 }
202
203 false
204 }
205
206 pub fn inverse(&self) -> &InverseJsonLdContext {
208 self.inverse.get_or_init(|| self.into())
209 }
210
211 pub fn set_normal(
213 &mut self,
214 key: JsonLdContextTerm,
215 definition: Option<JsonLdProcessedNormalTermDefinition>,
216 ) -> Option<JsonLdProcessedNormalTermDefinition> {
217 self.inverse.take();
218 self.definitions.set_normal(key, definition)
219 }
220
221 pub fn set_type(
223 &mut self,
224 type_: Option<JsonLdProcessedTypeTermDefinition>,
225 ) -> Option<JsonLdProcessedTypeTermDefinition> {
226 self.definitions.set_type(type_)
227 }
228
229 pub fn set_base_iri(&mut self, iri: Option<IriBuf>) {
231 self.inverse.take();
232 self.base_iri = iri
233 }
234
235 pub fn set_vocabulary(&mut self, vocab: Option<JsonLdTerm>) {
237 self.inverse.take();
238 self.vocabulary = vocab;
239 }
240
241 pub fn set_default_language(&mut self, lang: Option<JsonLdLenient<LangTagBuf>>) {
243 self.inverse.take();
244 self.default_language = lang;
245 }
246
247 pub fn set_default_base_direction(&mut self, dir: Option<JsonLdDirection>) {
249 self.inverse.take();
250 self.default_base_direction = dir;
251 }
252
253 pub fn set_previous_context(&mut self, previous: Self) {
255 self.inverse.take();
256 self.previous_context = Some(Box::new(previous))
257 }
258}
259
260impl Clone for RawJsonLdProcessedContext {
261 fn clone(&self) -> Self {
262 Self {
263 original_base_url: self.original_base_url.clone(),
264 base_iri: self.base_iri.clone(),
265 vocabulary: self.vocabulary.clone(),
266 default_language: self.default_language.clone(),
267 default_base_direction: self.default_base_direction,
268 previous_context: self.previous_context.clone(),
269 definitions: self.definitions.clone(),
270 inverse: OnceLock::default(),
271 }
272 }
273}
274
275impl PartialEq for RawJsonLdProcessedContext {
276 fn eq(&self, other: &Self) -> bool {
277 self.original_base_url == other.original_base_url
278 && self.base_iri == other.base_iri
279 && self.vocabulary == other.vocabulary
280 && self.default_language == other.default_language
281 && self.default_base_direction == other.default_base_direction
282 && self.previous_context == other.previous_context
283 }
284}