turtle_syntax_next/
build.rs

1use iref::{Iri, IriBuf, IriRef, IriRefBuf};
2use langtag::LangTagBuf;
3use rdf_types::vocabulary::{
4	self, BlankIdVocabulary, BlankIdVocabularyMut, IriVocabulary, IriVocabularyMut,
5};
6use rdf_types::{Generator, Id, LexicalTriple, LiteralType, Object, Subject, Term, Triple};
7use static_iref::iri;
8use std::collections::HashMap;
9
10const RDF_TYPE: &Iri = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#type");
11const RDF_LIST: &Iri = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#List");
12const RDF_NIL: &Iri = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#nil");
13const RDF_FIRST: &Iri = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#first");
14const RDF_REST: &Iri = iri!("http://www.w3.org/1999/02/22-rdf-syntax-ns#rest");
15const XSD_BOOLEAN: &Iri = iri!("http://www.w3.org/2001/XMLSchema#boolean");
16const XSD_INTEGER: &Iri = iri!("http://www.w3.org/2001/XMLSchema#integer");
17const XSD_DECIMAL: &Iri = iri!("http://www.w3.org/2001/XMLSchema#decimal");
18const XSD_DOUBLE: &Iri = iri!("http://www.w3.org/2001/XMLSchema#double");
19
20#[derive(Debug, thiserror::Error)]
21pub enum Error {
22	#[error("cannot resolve relative IRI <{0}>: no base IRI")]
23	NoBaseIri(IriRefBuf),
24
25	#[error("unknown IRI prefix `{0}`")]
26	UnknownPrefix(String),
27
28	#[error("invalid compact IRI suffix in `{prefix}:{invalid_suffix}`")]
29	InvalidCompactIriSuffix {
30		prefix: String,
31		iri: IriBuf,
32		invalid_suffix: String,
33	},
34}
35
36pub type BuildError<M> = (Box<Error>, M);
37
38pub type RdfId<V> = Id<<V as IriVocabulary>::Iri, <V as BlankIdVocabulary>::BlankId>;
39
40pub type MetaTriple<M, V = ()> = (
41	Triple<
42		(RdfId<V>, M),
43		(<V as IriVocabulary>::Iri, M),
44		(
45			Object<RdfId<V>, crate::RdfLiteral<M, <V as IriVocabulary>::Iri>>,
46			M,
47		),
48	>,
49	M,
50);
51
52impl<M: Clone> crate::Document<M> {
53	pub fn build_meta_triples(
54		&self,
55		base_iri: Option<IriBuf>,
56		mut generator: impl Generator<()>,
57	) -> Result<Vec<MetaTriple<M, ()>>, BuildError<M>> {
58		let mut triples = Vec::new();
59		let mut context = Context::new(base_iri, vocabulary::no_vocabulary_mut(), &mut generator);
60		self.build(&mut context, &mut triples)?;
61		Ok(triples)
62	}
63
64	pub fn build_meta_triples_with<V: RdfVocabulary + IriVocabularyMut + BlankIdVocabularyMut>(
65		&self,
66		base_iri: Option<V::Iri>,
67		vocabulary: &mut V,
68		mut generator: impl Generator<V>,
69	) -> Result<Vec<MetaTriple<M, V>>, BuildError<M>>
70	where
71		V::Iri: Clone,
72		V::BlankId: Clone,
73	{
74		let mut triples = Vec::new();
75		let mut context = Context::new(base_iri, vocabulary, &mut generator);
76		self.build(&mut context, &mut triples)?;
77		Ok(triples)
78	}
79
80	pub fn build_lexical_triples(
81		&self,
82		base_iri: Option<IriBuf>,
83		mut generator: impl Generator<()>,
84	) -> Result<Vec<LexicalTriple>, BuildError<M>> {
85		let triples = self.build_meta_triples(base_iri, &mut generator)?;
86
87		let triples = triples.into_iter().map(|triple| {
88			let o = match triple.0 .2 .0 {
89				Term::Id(id) => Term::Id::<rdf_types::Id, rdf_types::Literal>(id),
90				Term::Literal(literal) => Term::Literal(literal.into()),
91			};
92
93			LexicalTriple::new(triple.0 .0 .0, triple.0 .1 .0, o)
94		}).collect();
95
96		Ok(triples)
97	}
98}
99
100pub struct Context<'v, 'g, M, V: IriVocabulary, G> {
101	vocabulary: &'v mut V,
102	generator: &'g mut G,
103	base_iri: Option<V::Iri>,
104	prefixes: HashMap<String, (V::Iri, M)>,
105}
106
107impl<'v, 'g, M, V: IriVocabulary, G> Context<'v, 'g, M, V, G> {
108	pub fn new(base_iri: Option<V::Iri>, vocabulary: &'v mut V, generator: &'g mut G) -> Self {
109		Self {
110			vocabulary,
111			generator,
112			base_iri,
113			prefixes: HashMap::new(),
114		}
115	}
116
117	pub fn resolve_iri_ref(
118		&mut self,
119		(iri_ref, meta): (&IriRef, &M),
120	) -> Result<V::Iri, BuildError<M>>
121	where
122		M: Clone,
123		V: IriVocabularyMut,
124	{
125		match &self.base_iri {
126			Some(current) => {
127				let iri = iri_ref.resolved(self.vocabulary.iri(current).unwrap());
128				Ok(self.vocabulary.insert(iri.as_iri()))
129			}
130			None => match iri_ref.as_iri() {
131				Some(iri) => Ok(self.vocabulary.insert(iri)),
132				None => Err((Box::new(Error::NoBaseIri(iri_ref.to_owned())), meta.clone())),
133			},
134		}
135	}
136
137	pub fn resolve_compact_iri(
138		&mut self,
139		prefix: (&str, &M),
140		suffix: (&str, &M),
141		meta: &M,
142	) -> Result<V::Iri, BuildError<M>>
143	where
144		M: Clone,
145		V: IriVocabularyMut,
146	{
147		match self.prefixes.get(prefix.0) {
148			Some(iri) => {
149				let iri = self.vocabulary.iri(&iri.0).unwrap();
150				let mut buffer = iri.to_string();
151				buffer.push_str(suffix.0);
152				match Iri::new(&buffer) {
153					Ok(result) => Ok(self.vocabulary.insert(result)),
154					Err(_) => Err((
155						Box::new(Error::InvalidCompactIriSuffix {
156							prefix: prefix.0.to_owned(),
157							iri: iri.to_owned(),
158							invalid_suffix: suffix.0.to_owned(),
159						}),
160						meta.clone(),
161					)),
162				}
163			}
164			None => Err((
165				Box::new(Error::UnknownPrefix(prefix.0.to_owned())),
166				prefix.1.clone(),
167			)),
168		}
169	}
170
171	pub fn insert_prefix(&mut self, prefix: String, iri: V::Iri, meta: M) {
172		self.prefixes.insert(prefix, (iri, meta));
173	}
174}
175
176pub trait RdfVocabulary: IriVocabulary + BlankIdVocabulary {}
177
178impl<V> RdfVocabulary for V where V: IriVocabulary + BlankIdVocabulary {}
179
180pub trait Build<M, V: RdfVocabulary, G> {
181	fn build(
182		&self,
183		context: &mut Context<M, V, G>,
184		triples: &mut Vec<MetaTriple<M, V>>,
185	) -> Result<(), BuildError<M>>;
186}
187
188impl<M: Clone, V: RdfVocabulary + IriVocabularyMut + BlankIdVocabularyMut, G: Generator<V>>
189	Build<M, V, G> for crate::Document<M>
190where
191	V::Iri: Clone,
192	V::BlankId: Clone,
193{
194	fn build(
195		&self,
196		context: &mut Context<M, V, G>,
197		triples: &mut Vec<MetaTriple<M, V>>,
198	) -> Result<(), BuildError<M>> {
199		for statement in &self.statements {
200			match statement {
201				(crate::Statement::Directive(directive), meta) => match directive {
202					crate::Directive::Base(iri) | crate::Directive::SparqlBase(iri) => {
203						let iri_ref = (iri.0.as_iri_ref(), &iri.1);
204						context.base_iri = Some(context.resolve_iri_ref(iri_ref)?);
205					}
206					crate::Directive::Prefix(prefix, iri)
207					| crate::Directive::SparqlPrefix(prefix, iri) => {
208						let iri_ref = (iri.0.as_iri_ref(), &iri.1);
209						let iri = context.resolve_iri_ref(iri_ref)?;
210						context.insert_prefix(prefix.0.clone(), iri, meta.clone());
211					}
212				},
213				(crate::Statement::Triples(t), meta) => {
214					t.build(context, meta, triples)?;
215				}
216			}
217		}
218
219		Ok(())
220	}
221}
222
223impl<M: Clone> crate::Triples<M> {
224	fn build<V: RdfVocabulary + IriVocabularyMut + BlankIdVocabularyMut, G: Generator<V>>(
225		&self,
226		context: &mut Context<M, V, G>,
227		meta: &M,
228		triples: &mut Vec<MetaTriple<M, V>>,
229	) -> Result<(), BuildError<M>>
230	where
231		V::Iri: Clone,
232		V::BlankId: Clone,
233	{
234		let subject = self.subject.build(context, triples)?;
235
236		for (po_list, _) in self.predicate_objects_list.0.iter() {
237			po_list.build(context, meta, &subject, triples)?;
238		}
239
240		Ok(())
241	}
242}
243
244impl<M: Clone> crate::PredicateObjects<M> {
245	fn build<V: RdfVocabulary + IriVocabularyMut + BlankIdVocabularyMut, G: Generator<V>>(
246		&self,
247		context: &mut Context<M, V, G>,
248		meta: &M,
249		subject: &(Subject<V::Iri, V::BlankId>, M),
250		triples: &mut Vec<MetaTriple<M, V>>,
251	) -> Result<(), BuildError<M>>
252	where
253		V::Iri: Clone,
254		V::BlankId: Clone,
255	{
256		let predicate = self.verb.build(context, triples)?;
257
258		for o in &self.objects.0 .0 {
259			let object = o.build(context, triples)?;
260			triples.push((
261				Triple(subject.clone(), predicate.clone(), object),
262				meta.clone(),
263			))
264		}
265
266		Ok(())
267	}
268}
269
270trait BuildFragment<M, V: RdfVocabulary + BlankIdVocabulary, G> {
271	type Target;
272
273	fn build(
274		&self,
275		context: &mut Context<M, V, G>,
276		triples: &mut Vec<MetaTriple<M, V>>,
277	) -> Result<Self::Target, BuildError<M>>;
278}
279
280impl<T: BuildMetaFragment<M, V, G>, M: Clone, V: RdfVocabulary + BlankIdVocabulary, G>
281	BuildFragment<M, V, G> for (T, M)
282{
283	type Target = (T::Target, M);
284
285	fn build(
286		&self,
287		context: &mut Context<M, V, G>,
288		triples: &mut Vec<MetaTriple<M, V>>,
289	) -> Result<Self::Target, BuildError<M>> {
290		Ok((self.0.build(context, &self.1, triples)?, self.1.clone()))
291	}
292}
293
294trait BuildMetaFragment<M, V: RdfVocabulary, G> {
295	type Target;
296
297	fn build(
298		&self,
299		context: &mut Context<M, V, G>,
300		meta: &M,
301		triples: &mut Vec<MetaTriple<M, V>>,
302	) -> Result<Self::Target, BuildError<M>>;
303}
304
305impl<M: Clone, V: RdfVocabulary + IriVocabularyMut + BlankIdVocabulary, G>
306	BuildMetaFragment<M, V, G> for crate::Iri<M>
307{
308	type Target = V::Iri;
309
310	fn build(
311		&self,
312		context: &mut Context<M, V, G>,
313		meta: &M,
314		_triples: &mut Vec<MetaTriple<M, V>>,
315	) -> Result<Self::Target, BuildError<M>> {
316		match self {
317			Self::IriRef(iri_ref) => context.resolve_iri_ref((iri_ref.as_iri_ref(), meta)),
318			Self::PrefixedName(prefix, suffix) => {
319				context.resolve_compact_iri((&prefix.0, &prefix.1), (&suffix.0, &suffix.1), meta)
320			}
321		}
322	}
323}
324
325impl<M: Clone, V: RdfVocabulary, G: Generator<V>> BuildMetaFragment<M, V, G> for crate::BlankNode<M>
326where
327	V: IriVocabularyMut + BlankIdVocabularyMut,
328	V::Iri: Clone,
329	V::BlankId: Clone,
330{
331	type Target = Subject<V::Iri, V::BlankId>;
332
333	fn build(
334		&self,
335		context: &mut Context<M, V, G>,
336		meta: &M,
337		triples: &mut Vec<MetaTriple<M, V>>,
338	) -> Result<Self::Target, BuildError<M>> {
339		match self {
340			Self::Label(b) => Ok(Subject::Blank(context.vocabulary.insert_blank_id(b))),
341			Self::Anonymous(b_property_list) => {
342				let b = (context.generator.next(context.vocabulary), meta.clone());
343
344				for (predicate_objects, meta) in b_property_list.0.iter() {
345					predicate_objects.build(context, meta, &b, triples)?;
346				}
347
348				Ok(b.0)
349			}
350		}
351	}
352}
353
354impl<M: Clone, V: RdfVocabulary, G: Generator<V>> BuildMetaFragment<M, V, G> for crate::Subject<M>
355where
356	V: IriVocabularyMut + BlankIdVocabularyMut,
357	V::Iri: Clone,
358	V::BlankId: Clone,
359{
360	type Target = Subject<V::Iri, V::BlankId>;
361
362	fn build(
363		&self,
364		context: &mut Context<M, V, G>,
365		meta: &M,
366		triples: &mut Vec<MetaTriple<M, V>>,
367	) -> Result<Self::Target, BuildError<M>> {
368		match self {
369			Self::Iri(iri) => Ok(Subject::Iri(iri.build(context, meta, triples)?)),
370			Self::BlankNode(b) => Ok(b.build(context, meta, triples)?),
371			Self::Collection(collection) => collection.build(context, meta, triples),
372		}
373	}
374}
375impl<M: Clone, V: RdfVocabulary, G: Generator<V>> BuildMetaFragment<M, V, G>
376	for crate::Collection<M>
377where
378	V: IriVocabularyMut + BlankIdVocabularyMut,
379	V::Iri: Clone,
380	V::BlankId: Clone,
381{
382	type Target = Subject<V::Iri, V::BlankId>;
383
384	fn build(
385		&self,
386		context: &mut Context<M, V, G>,
387		meta: &M,
388		triples: &mut Vec<MetaTriple<M, V>>,
389	) -> Result<Self::Target, BuildError<M>> {
390		let mut head = Subject::Iri(context.vocabulary.insert(RDF_NIL));
391
392		for o in self.0.iter().rev() {
393			let item = o.build(context, triples)?;
394			let node = context.generator.next(context.vocabulary);
395
396			triples.push((
397				Triple(
398					(node.clone(), item.1.clone()),
399					(context.vocabulary.insert(RDF_TYPE), item.1.clone()),
400					(
401						Term::Id(Id::Iri(context.vocabulary.insert(RDF_LIST))),
402						item.1.clone(),
403					),
404				),
405				meta.clone(),
406			));
407
408			triples.push((
409				Triple(
410					(node.clone(), item.1.clone()),
411					(context.vocabulary.insert(RDF_REST), item.1.clone()),
412					(head.into_term(), item.1.clone()),
413				),
414				meta.clone(),
415			));
416
417			triples.push((
418				Triple(
419					(node.clone(), item.1.clone()),
420					(context.vocabulary.insert(RDF_FIRST), item.1.clone()),
421					item,
422				),
423				meta.clone(),
424			));
425
426			head = node;
427		}
428
429		Ok(head)
430	}
431}
432
433impl<M: Clone, V: RdfVocabulary + IriVocabularyMut, G> BuildMetaFragment<M, V, G>
434	for crate::Verb<M>
435{
436	type Target = V::Iri;
437
438	fn build(
439		&self,
440		context: &mut Context<M, V, G>,
441		meta: &M,
442		triples: &mut Vec<MetaTriple<M, V>>,
443	) -> Result<Self::Target, BuildError<M>> {
444		match self {
445			Self::A => Ok(context.vocabulary.insert(RDF_TYPE)),
446			Self::Predicate(i) => i.build(context, meta, triples),
447		}
448	}
449}
450
451impl<M: Clone, V: RdfVocabulary, G: Generator<V>> BuildMetaFragment<M, V, G> for crate::Object<M>
452where
453	V: IriVocabularyMut + BlankIdVocabularyMut,
454	V::Iri: Clone,
455	V::BlankId: Clone,
456{
457	type Target = Object<Id<V::Iri, V::BlankId>, crate::RdfLiteral<M, V::Iri>>;
458
459	fn build(
460		&self,
461		context: &mut Context<M, V, G>,
462		meta: &M,
463		triples: &mut Vec<MetaTriple<M, V>>,
464	) -> Result<Self::Target, BuildError<M>> {
465		match self {
466			Self::Iri(iri) => Ok(Object::Id(Id::Iri(iri.build(context, meta, triples)?))),
467			Self::BlankNode(b) => Ok(b.build(context, meta, triples)?.into_term()),
468			Self::Collection(collection) => {
469				Ok(collection.build(context, meta, triples)?.into_term())
470			}
471			Self::Literal(literal) => Ok(Object::Literal(literal.build(context, meta, triples)?)),
472		}
473	}
474}
475
476impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for crate::Literal<M>
477where
478	V: IriVocabularyMut + BlankIdVocabulary,
479{
480	type Target = crate::RdfLiteral<M, V::Iri>;
481
482	fn build(
483		&self,
484		context: &mut Context<M, V, G>,
485		meta: &M,
486		triples: &mut Vec<MetaTriple<M, V>>,
487	) -> Result<Self::Target, BuildError<M>> {
488		match self {
489			Self::Boolean(b) => b.build(context, meta, triples),
490			Self::Numeric(n) => n.build(context, meta, triples),
491			Self::Rdf(literal) => literal.build(context, meta, triples),
492		}
493	}
494}
495
496impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for bool
497where
498	V: IriVocabularyMut + BlankIdVocabulary,
499{
500	type Target = crate::RdfLiteral<M, V::Iri>;
501
502	fn build(
503		&self,
504		context: &mut Context<M, V, G>,
505		meta: &M,
506		_triples: &mut Vec<MetaTriple<M, V>>,
507	) -> Result<Self::Target, BuildError<M>> {
508		let s = if *self { "true" } else { "false" };
509
510		Ok(crate::RdfLiteral {
511			value: (s.to_owned(), meta.clone()),
512			type_: (
513				LiteralType::Any(context.vocabulary.insert(XSD_BOOLEAN)),
514				meta.clone(),
515			),
516		})
517	}
518}
519
520impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for crate::NumericLiteral
521where
522	V: IriVocabularyMut + BlankIdVocabulary,
523{
524	type Target = crate::RdfLiteral<M, V::Iri>;
525
526	fn build(
527		&self,
528		context: &mut Context<M, V, G>,
529		meta: &M,
530		_triples: &mut Vec<MetaTriple<M, V>>,
531	) -> Result<Self::Target, BuildError<M>> {
532		let (s, ty) = match self {
533			Self::Integer(i) => (i.as_str(), XSD_INTEGER),
534			Self::Decimal(d) => (d.as_str(), XSD_DECIMAL),
535			Self::Double(d) => (d.as_str(), XSD_DOUBLE),
536		};
537
538		Ok(crate::RdfLiteral::new(
539			(s.to_owned(), meta.clone()),
540			(
541				LiteralType::Any(context.vocabulary.insert(ty)),
542				meta.clone(),
543			),
544		))
545	}
546}
547
548impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for crate::RdfLiteral<M>
549where
550	V: IriVocabularyMut + BlankIdVocabulary,
551{
552	type Target = crate::RdfLiteral<M, V::Iri>;
553
554	fn build(
555		&self,
556		context: &mut Context<M, V, G>,
557		_meta: &M,
558		triples: &mut Vec<MetaTriple<M, V>>,
559	) -> Result<Self::Target, BuildError<M>> {
560		let type_ = match &self.type_ {
561			(LiteralType::Any(t), meta) => (
562				LiteralType::Any(t.build(context, meta, triples)?),
563				meta.clone(),
564			),
565			(LiteralType::LangString(tag), meta) => (
566				LiteralType::LangString(tag.build(context, meta, triples)?),
567				meta.clone(),
568			),
569		};
570
571		Ok(crate::RdfLiteral::new(self.value.clone(), type_))
572	}
573}
574
575impl<M: Clone, V: RdfVocabulary, G> BuildMetaFragment<M, V, G> for LangTagBuf {
576	type Target = LangTagBuf;
577
578	fn build(
579		&self,
580		_context: &mut Context<M, V, G>,
581		_meta: &M,
582		_triples: &mut Vec<MetaTriple<M, V>>,
583	) -> Result<Self::Target, BuildError<M>> {
584		// NOTE Clone needed?
585		Ok(self.clone())
586	}
587}