turtle_syntax/
build.rs

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