1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
//! Lexical domain abstractions.
//!
//! Having to store, clone and compare blank ids, IRIs and literals is expensive
//! and may become a burden to a RDF-intensive application. This modules defines
//! the [`Vocabulary`] trait (and similar traits) to abstract away the lexical
//! representation of resources.
//!
//! Using vocabularies, an IRI can be represented as a simple integer, or enum
//! type, drastically reducing the cost of storage and comparison.
mod blank_id;
mod iri;
mod literal;

pub use blank_id::*;
use iref::IriBuf;
pub use iri::*;
pub use literal::*;

mod r#impl;
pub use r#impl::*;

/// Vocabulary.
///
/// A vocabulary is a collection that stores the lexical representation of
/// IRIs and blank node identifiers.
/// This allows the use of custom lightweight types to store, copy and compare
/// IRIs and blank IDs.
///
/// Any vocabulary implements the `Namespace` trait.
pub trait Vocabulary: IriVocabulary + BlankIdVocabulary + LiteralVocabulary {}

/// Mutable vocabulary.
pub trait VocabularyMut:
	Vocabulary + IriVocabularyMut + BlankIdVocabularyMut + LiteralVocabularyMut
{
}

impl<V: IriVocabulary + BlankIdVocabulary + LiteralVocabulary> Vocabulary for V {}

impl<V: IriVocabularyMut + BlankIdVocabularyMut + LiteralVocabularyMut> VocabularyMut for V {}

/// Value that can be embedded into the given vocabulary by consuming it.
pub trait EmbedIntoVocabulary<V> {
	/// Type of the value once embedded into the vocabulary.
	type Embedded;

	fn embed_into_vocabulary(self, vocabulary: &mut V) -> Self::Embedded;
}

impl<V, T: EmbedIntoVocabulary<V>> EmbedIntoVocabulary<V> for Vec<T> {
	type Embedded = Vec<T::Embedded>;

	fn embed_into_vocabulary(self, vocabulary: &mut V) -> Self::Embedded {
		self.into_iter()
			.map(|t| t.embed_into_vocabulary(vocabulary))
			.collect()
	}
}

impl<V, T: EmbedIntoVocabulary<V>> EmbedIntoVocabulary<V> for Option<T> {
	type Embedded = Option<T::Embedded>;

	fn embed_into_vocabulary(self, vocabulary: &mut V) -> Self::Embedded {
		self.map(|t| t.embed_into_vocabulary(vocabulary))
	}
}

/// Value that can be embedded into the given vocabulary without consuming it.
pub trait EmbeddedIntoVocabulary<V> {
	type Embedded;

	fn embedded_into_vocabulary(&self, vocabulary: &mut V) -> Self::Embedded;
}

impl<V, T: EmbeddedIntoVocabulary<V>> EmbeddedIntoVocabulary<V> for Vec<T> {
	type Embedded = Vec<T::Embedded>;

	fn embedded_into_vocabulary(&self, vocabulary: &mut V) -> Self::Embedded {
		self.iter()
			.map(|t| t.embedded_into_vocabulary(vocabulary))
			.collect()
	}
}

impl<V, T: EmbeddedIntoVocabulary<V>> EmbeddedIntoVocabulary<V> for Option<T> {
	type Embedded = Option<T::Embedded>;

	fn embedded_into_vocabulary(&self, vocabulary: &mut V) -> Self::Embedded {
		self.as_ref()
			.map(|t| t.embedded_into_vocabulary(vocabulary))
	}
}

/// Wrapper type to allow
/// `Term<Id<&V::Iri, &V::BlankId>, &V::Literal>` to be extracted into `Term`
/// using the `ExtractFromVocabulary<V>` trait.
///
/// There is a limitation in Rust's trait solver forbidding the implementation
/// of `ExtractFromVocabulary<V>` for both
/// `Term<Id<V::Iri, V::BlankId>, V::Literal>` and
/// `Term<Id<&V::Iri, &V::BlankId>, &V::Literal>`.
/// It is detected as a conflicting implementation although an associated type
/// `T::Assoc` can never be equal to its reference `&T::Assoc`.
///
/// As a workaround, `ExtractFromVocabulary` is implemented for
/// `ExtractFromVocabulary<V>` is implemented for
/// `ByRef<Term<Id<&V::Iri, &V::BlankId>, &V::Literal>>` instead.
///
/// # Example
///
/// ```
/// use rdf_types::{Id, Term, vocabulary::{IndexVocabulary, IriVocabularyMut, IriIndex, BlankIdIndex, LiteralIndex, ExtractFromVocabulary, ByRef}};
/// use static_iref::iri;
///
/// let mut vocabulary = IndexVocabulary::new();
///
/// let iri = vocabulary.insert(iri!("http://example.org/"));
/// let term: Term<Id<&IriIndex, &BlankIdIndex>, &LiteralIndex> = Term::iri(&iri);
///
/// let _: Term = ByRef(term).extract_from_vocabulary(&vocabulary);
/// ```
pub struct ByRef<T>(pub T);

/// Wrapper type to allow an arbitrary type to be recognized as an RDF
/// IRI predicate.
///
/// # Example
///
/// ```
/// use rdf_types::{Id, Term, Quad, LexicalQuad, vocabulary::{IndexVocabulary, IriVocabularyMut, IriIndex, BlankIdIndex, LiteralIndex, ExtractFromVocabulary, Predicate, ByRef}};
/// use static_iref::iri;
///
/// let mut vocabulary = IndexVocabulary::new();
///
/// type IdRef<'a> = Id<&'a IriIndex, &'a BlankIdIndex>;
/// type TermRef<'a> = Term<IdRef<'a>, &'a LiteralIndex>;
/// type QuadRef<'a> = Quad<IdRef<'a>, &'a IriIndex, TermRef<'a>, IdRef<'a>>;
///
/// let subject = vocabulary.insert(iri!("http://example.org/#subject"));
/// let predicate = vocabulary.insert(iri!("http://example.org/#property"));
/// let object = vocabulary.insert(iri!("http://example.org/#object"));
///
/// let quad: QuadRef = Quad(
///   Id::Iri(&subject),
///   &predicate,
///   Term::iri(&object),
///   None
/// );
///
/// let _: LexicalQuad = ByRef(
///     quad.map_predicate(Predicate) // ensures the `&IriIndex` type is interpreted as a predicate.
/// ).extract_from_vocabulary(&vocabulary);
/// ```
pub struct Predicate<T>(pub T);

impl<V: IriVocabulary> ExtractedFromVocabulary<V> for Predicate<V::Iri> {
	type Extracted = IriBuf;

	fn extracted_from_vocabulary(&self, vocabulary: &V) -> Self::Extracted {
		vocabulary.iri(&self.0).unwrap().to_owned()
	}
}

impl<V: IriVocabulary> ExtractFromVocabulary<V> for Predicate<V::Iri> {
	type Extracted = IriBuf;

	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
		vocabulary.owned_iri(self.0).ok().unwrap()
	}
}

impl<'a, V: IriVocabulary> ExtractFromVocabulary<V> for ByRef<Predicate<&'a V::Iri>> {
	type Extracted = IriBuf;

	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
		vocabulary.iri(self.0 .0).unwrap().to_owned()
	}
}

/// Extract the RDF component values (IRIs, blank node identifiers, etc.)
/// embedded into the vocabulary `V`.
///
/// For `V::Iri` the output will be `IriBuf`, for `V::BlankId` it will be
/// `BlankIdBuf`, etc.
pub trait ExtractFromVocabulary<V> {
	type Extracted;

	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted;
}

impl<T: ExtractFromVocabulary<V>, V> ExtractFromVocabulary<V> for Option<T> {
	type Extracted = Option<T::Extracted>;

	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
		self.map(|t| t.extract_from_vocabulary(vocabulary))
	}
}

impl<T, V> ExtractFromVocabulary<V> for ByRef<Option<T>>
where
	ByRef<T>: ExtractFromVocabulary<V>,
{
	type Extracted = Option<<ByRef<T> as ExtractFromVocabulary<V>>::Extracted>;

	fn extract_from_vocabulary(self, vocabulary: &V) -> Self::Extracted {
		self.0.map(|t| ByRef(t).extract_from_vocabulary(vocabulary))
	}
}

/// Exports the RDF component values (IRIs, blank node identifiers, etc.)
/// embedded into the vocabulary `V`.
///
/// This trait is similar to `ExportFromVocabulary` but will clone the component
/// values. For `V::Iri` the output will be `IriBuf`, for `V::BlankId` it will be
/// `BlankIdBuf`, etc.
pub trait ExtractedFromVocabulary<V> {
	type Extracted;

	/// Exports a value embedded into the vocabulary `V`.
	///
	/// For `V::Iri` the output will be `IriBuf`, for `V::BlankId` it will be
	/// `BlankIdBuf`, etc.
	fn extracted_from_vocabulary(&self, vocabulary: &V) -> Self::Extracted;
}

impl<T: ExtractedFromVocabulary<V>, V> ExtractedFromVocabulary<V> for Option<T> {
	type Extracted = Option<T::Extracted>;

	fn extracted_from_vocabulary(&self, vocabulary: &V) -> Self::Extracted {
		self.as_ref()
			.map(|t| t.extracted_from_vocabulary(vocabulary))
	}
}

/// Try to extract the RDF component values (IRIs, blank node identifiers, etc.)
/// embedded into the vocabulary `V`. This is the fallible version of
/// [`ExtractFromVocabulary`].
///
/// For `V::Iri` the output will be `IriBuf`, for `V::BlankId` it will be
/// `BlankIdBuf`, etc.
pub trait TryExtractFromVocabulary<V> {
	type Extracted;

	type Error;

	fn try_extract_from_vocabulary(self, vocabulary: &V) -> Result<Self::Extracted, Self::Error>;
}

impl<V, T: TryExtractFromVocabulary<V>> TryExtractFromVocabulary<V> for Option<T> {
	type Extracted = Option<T::Extracted>;

	type Error = T::Error;

	fn try_extract_from_vocabulary(self, vocabulary: &V) -> Result<Self::Extracted, Self::Error> {
		self.map(|t| t.try_extract_from_vocabulary(vocabulary))
			.transpose()
	}
}