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()
}
}