json_ld_syntax/context/definition/
mod.rs1use super::{term_definition, TermDefinition};
2use crate::{Direction, Keyword, LenientLangTagBuf, Nullable};
3use educe::Educe;
4use indexmap::IndexMap;
5use iref::IriRefBuf;
6
7mod import;
8mod key;
9mod reference;
10mod type_;
11mod version;
12mod vocab;
13
14pub use import::*;
15pub use key::*;
16pub use reference::*;
17pub use type_::*;
18pub use version::*;
19pub use vocab::*;
20
21#[derive(PartialEq, Eq, Clone, Educe, Debug)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24#[educe(Default)]
25pub struct Definition {
26 #[cfg_attr(
27 feature = "serde",
28 serde(
29 rename = "@base",
30 default,
31 deserialize_with = "Nullable::optional",
32 skip_serializing_if = "Option::is_none"
33 )
34 )]
35 pub base: Option<Nullable<IriRefBuf>>,
36
37 #[cfg_attr(
38 feature = "serde",
39 serde(rename = "@import", default, skip_serializing_if = "Option::is_none")
40 )]
41 pub import: Option<IriRefBuf>,
42
43 #[cfg_attr(
44 feature = "serde",
45 serde(
46 rename = "@language",
47 default,
48 deserialize_with = "Nullable::optional",
49 skip_serializing_if = "Option::is_none"
50 )
51 )]
52 pub language: Option<Nullable<LenientLangTagBuf>>,
53
54 #[cfg_attr(
55 feature = "serde",
56 serde(
57 rename = "@direction",
58 default,
59 deserialize_with = "Nullable::optional",
60 skip_serializing_if = "Option::is_none"
61 )
62 )]
63 pub direction: Option<Nullable<Direction>>,
64
65 #[cfg_attr(
66 feature = "serde",
67 serde(
68 rename = "@propagate",
69 default,
70 skip_serializing_if = "Option::is_none"
71 )
72 )]
73 pub propagate: Option<bool>,
74
75 #[cfg_attr(
76 feature = "serde",
77 serde(
78 rename = "@protected",
79 default,
80 skip_serializing_if = "Option::is_none"
81 )
82 )]
83 pub protected: Option<bool>,
84
85 #[cfg_attr(
86 feature = "serde",
87 serde(rename = "@type", default, skip_serializing_if = "Option::is_none")
88 )]
89 pub type_: Option<Type>,
90
91 #[cfg_attr(
92 feature = "serde",
93 serde(rename = "@version", default, skip_serializing_if = "Option::is_none")
94 )]
95 pub version: Option<Version>,
96
97 #[cfg_attr(
98 feature = "serde",
99 serde(
100 rename = "@vocab",
101 default,
102 deserialize_with = "Nullable::optional",
103 skip_serializing_if = "Option::is_none"
104 )
105 )]
106 pub vocab: Option<Nullable<Vocab>>,
107
108 #[cfg_attr(feature = "serde", serde(flatten))]
109 pub bindings: Bindings,
110}
111
112impl Definition {
113 pub fn new() -> Self {
114 Self::default()
115 }
116
117 pub fn get(&self, key: &KeyOrKeyword) -> Option<EntryValueRef> {
118 match key {
119 KeyOrKeyword::Keyword(k) => match k {
120 Keyword::Base => self
121 .base
122 .as_ref()
123 .map(Nullable::as_deref)
124 .map(EntryValueRef::Base),
125 Keyword::Import => self.import.as_deref().map(EntryValueRef::Import),
126 Keyword::Language => self
127 .language
128 .as_ref()
129 .map(Nullable::as_ref)
130 .map(EntryValueRef::Language),
131 Keyword::Direction => self.direction.map(EntryValueRef::Direction),
132 Keyword::Propagate => self.propagate.map(EntryValueRef::Propagate),
133 Keyword::Protected => self.protected.map(EntryValueRef::Protected),
134 Keyword::Type => self.type_.map(EntryValueRef::Type),
135 Keyword::Version => self.version.map(EntryValueRef::Version),
136 Keyword::Vocab => self
137 .vocab
138 .as_ref()
139 .map(Nullable::as_ref)
140 .map(EntryValueRef::Vocab),
141 _ => None,
142 },
143 KeyOrKeyword::Key(k) => self.bindings.get(k).map(EntryValueRef::Definition),
144 }
145 }
146
147 pub fn get_binding(&self, key: &Key) -> Option<Nullable<&TermDefinition>> {
148 self.bindings.get(key)
149 }
150}
151
152#[derive(PartialEq, Eq, Clone, Educe, Debug)]
154#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
155#[cfg_attr(feature = "serde", serde(transparent))]
156#[educe(Default)]
157pub struct Bindings(IndexMap<Key, Nullable<TermDefinition>>);
158
159pub struct BindingsIter<'a>(indexmap::map::Iter<'a, Key, Nullable<TermDefinition>>);
160
161impl<'a> Iterator for BindingsIter<'a> {
162 type Item = (&'a Key, Nullable<&'a TermDefinition>);
163
164 fn next(&mut self) -> Option<Self::Item> {
165 self.0.next().map(|(k, d)| (k, d.as_ref()))
166 }
167}
168
169impl<'a> DoubleEndedIterator for BindingsIter<'a> {
170 fn next_back(&mut self) -> Option<Self::Item> {
171 self.0.next_back().map(|(k, d)| (k, d.as_ref()))
172 }
173}
174
175impl<'a> ExactSizeIterator for BindingsIter<'a> {}
176
177impl Bindings {
178 pub fn insert(
179 &mut self,
180 key: Key,
181 def: Nullable<TermDefinition>,
182 ) -> Option<Nullable<TermDefinition>> {
183 self.0.insert(key, def)
184 }
185}
186
187impl Bindings {
188 pub fn new() -> Self {
189 Self::default()
190 }
191
192 pub fn len(&self) -> usize {
193 self.0.len()
194 }
195
196 pub fn is_empty(&self) -> bool {
197 self.0.is_empty()
198 }
199
200 pub fn get(&self, key: &Key) -> Option<Nullable<&TermDefinition>> {
201 self.0.get(key).map(Nullable::as_ref)
202 }
203
204 pub fn get_entry(&self, i: usize) -> Option<(&Key, Nullable<&TermDefinition>)> {
205 self.0
206 .get_index(i)
207 .map(|(key, value)| (key, value.as_ref()))
208 }
209
210 pub fn iter(&self) -> BindingsIter {
211 BindingsIter(self.0.iter())
212 }
213
214 pub fn insert_with(
215 &mut self,
216 key: Key,
217 def: Nullable<TermDefinition>,
218 ) -> Option<Nullable<TermDefinition>> {
219 self.0.insert(key, def)
220 }
221}
222
223impl IntoIterator for Bindings {
224 type Item = (Key, Nullable<TermDefinition>);
225 type IntoIter = indexmap::map::IntoIter<Key, Nullable<TermDefinition>>;
226
227 fn into_iter(self) -> Self::IntoIter {
228 self.0.into_iter()
229 }
230}
231
232impl FromIterator<(Key, Nullable<TermDefinition>)> for Bindings {
233 fn from_iter<T: IntoIterator<Item = (Key, Nullable<TermDefinition>)>>(iter: T) -> Self {
234 let mut result = Self::new();
235
236 for (key, binding) in iter {
237 result.0.insert(key, binding);
238 }
239
240 result
241 }
242}
243
244pub enum FragmentRef<'a> {
246 Entry(EntryRef<'a>),
248
249 Key(EntryKeyRef<'a>),
251
252 Value(EntryValueRef<'a>),
254
255 TermDefinitionFragment(term_definition::FragmentRef<'a>),
257}
258
259impl<'a> FragmentRef<'a> {
260 pub fn is_key(&self) -> bool {
261 match self {
262 Self::Key(_) => true,
263 Self::TermDefinitionFragment(f) => f.is_key(),
264 _ => false,
265 }
266 }
267
268 pub fn is_entry(&self) -> bool {
269 match self {
270 Self::Entry(_) => true,
271 Self::TermDefinitionFragment(f) => f.is_entry(),
272 _ => false,
273 }
274 }
275
276 pub fn is_array(&self) -> bool {
277 match self {
278 Self::TermDefinitionFragment(i) => i.is_array(),
279 _ => false,
280 }
281 }
282
283 pub fn is_object(&self) -> bool {
284 match self {
285 Self::Value(v) => v.is_object(),
286 Self::TermDefinitionFragment(v) => v.is_object(),
287 _ => false,
288 }
289 }
290
291 pub fn sub_items(&self) -> SubItems<'a> {
292 match self {
293 Self::Entry(e) => SubItems::Entry(Some(e.key()), Some(Box::new(e.value()))),
294 Self::Key(_) => SubItems::None,
295 Self::Value(v) => SubItems::Value(v.sub_items()),
296 Self::TermDefinitionFragment(f) => SubItems::TermDefinitionFragment(f.sub_fragments()),
297 }
298 }
299}
300
301pub enum EntryValueSubItems<'a> {
302 None,
303 TermDefinitionFragment(Box<term_definition::Entries<'a>>),
304}
305
306impl<'a> Iterator for EntryValueSubItems<'a> {
307 type Item = FragmentRef<'a>;
308
309 fn next(&mut self) -> Option<Self::Item> {
310 match self {
311 Self::None => None,
312 Self::TermDefinitionFragment(d) => d.next().map(|e| {
313 FragmentRef::TermDefinitionFragment(term_definition::FragmentRef::Entry(e))
314 }),
315 }
316 }
317}
318
319pub enum SubItems<'a> {
320 None,
321 Entry(Option<EntryKeyRef<'a>>, Option<Box<EntryValueRef<'a>>>),
322 Value(EntryValueSubItems<'a>),
323 TermDefinitionFragment(term_definition::SubFragments<'a>),
324}
325
326impl<'a> Iterator for SubItems<'a> {
327 type Item = FragmentRef<'a>;
328
329 fn next(&mut self) -> Option<Self::Item> {
330 match self {
331 Self::None => None,
332 Self::Entry(k, v) => k
333 .take()
334 .map(FragmentRef::Key)
335 .or_else(|| v.take().map(|v| FragmentRef::Value(*v))),
336 Self::Value(d) => d.next(),
337 Self::TermDefinitionFragment(d) => d.next().map(FragmentRef::TermDefinitionFragment),
338 }
339 }
340}
341
342#[cfg(test)]
343mod tests {
344 use super::Definition;
345
346 #[test]
347 fn deserialize_null_vocab() {
348 let definition: Definition = json_syntax::from_value(json_syntax::json!({
349 "@vocab": null
350 }))
351 .unwrap();
352 assert_eq!(definition.vocab, Some(crate::Nullable::Null))
353 }
354
355 #[test]
356 fn deserialize_no_vocab() {
357 let definition: Definition = json_syntax::from_value(json_syntax::json!({})).unwrap();
358 assert_eq!(definition.vocab, None)
359 }
360}