use crate::compaction::{self, Compact, CompactMeta};
use crate::context_processing::{self, Process, ProcessMeta, Processed};
use crate::expansion;
use crate::syntax::{self, ErrorCode};
use crate::{
id::Generator, ConflictingIndexes, Context, ContextLoader, ExpandedDocument, Loader,
ProcessingMode, RemoteDocumentReference,
};
use futures::future::BoxFuture;
use futures::FutureExt;
use json_ld_core::rdf::RdfDirection;
use json_ld_core::RdfQuads;
use locspan::{Location, Meta};
use rdf_types::vocabulary::Index;
use rdf_types::{vocabulary, IriVocabulary, Vocabulary, VocabularyMut};
use std::hash::Hash;
mod remote_document;
#[derive(Clone)]
pub struct Options<I = Index, M = Location<I>, C = json_ld_syntax::context::Value<M>> {
pub base: Option<I>,
pub compact_arrays: bool,
pub compact_to_relative: bool,
pub expand_context: Option<RemoteDocumentReference<I, M, C>>,
pub ordered: bool,
pub processing_mode: ProcessingMode,
pub rdf_direction: Option<RdfDirection>,
pub produce_generalized_rdf: bool,
pub expansion_policy: expansion::Policy,
}
impl<I, M, C> Options<I, M, C> {
pub fn unordered(self) -> Self {
Self {
ordered: false,
..self
}
}
pub fn with_expand_context(self, context: RemoteDocumentReference<I, M, C>) -> Self {
Self {
expand_context: Some(context),
..self
}
}
pub fn context_processing_options(&self) -> context_processing::Options {
context_processing::Options {
processing_mode: self.processing_mode,
..Default::default()
}
}
pub fn expansion_options(&self) -> expansion::Options {
expansion::Options {
processing_mode: self.processing_mode,
ordered: self.ordered,
policy: self.expansion_policy,
}
}
pub fn compaction_options(&self) -> compaction::Options {
compaction::Options {
processing_mode: self.processing_mode,
compact_to_relative: self.compact_to_relative,
compact_arrays: self.compact_arrays,
ordered: self.ordered,
}
}
}
impl<I, M, C> Default for Options<I, M, C> {
fn default() -> Self {
Self {
base: None,
compact_arrays: true,
compact_to_relative: true,
expand_context: None,
ordered: false,
processing_mode: ProcessingMode::JsonLd1_1,
rdf_direction: None,
produce_generalized_rdf: false,
expansion_policy: expansion::Policy::default(),
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum ExpandError<M, E, C> {
#[error("Expansion failed: {0}")]
Expansion(Meta<expansion::Error<M, C>, M>),
#[error("Context processing failed: {0}")]
ContextProcessing(Meta<context_processing::Error<C>, M>),
#[error("Remote document loading failed: {0}")]
Loading(E),
#[error("Remote context loading failed: {0}")]
ContextLoading(C),
}
impl<M, E, C> ExpandError<M, E, C> {
pub fn code(&self) -> ErrorCode {
match self {
Self::Expansion(e) => e.code(),
Self::ContextProcessing(e) => e.code(),
Self::Loading(_) => ErrorCode::LoadingDocumentFailed,
Self::ContextLoading(_) => ErrorCode::LoadingRemoteContextFailed,
}
}
}
pub type ExpandResult<I, B, M, L> = Result<
Meta<ExpandedDocument<I, B, M>, M>,
ExpandError<M, <L as Loader<I, M>>::Error, <L as ContextLoader<I, M>>::ContextError>,
>;
#[derive(Debug, thiserror::Error)]
pub enum CompactError<M, E, C> {
#[error("Expansion failed: {0}")]
Expand(ExpandError<M, E, C>),
#[error("Context processing failed: {0}")]
ContextProcessing(Meta<context_processing::Error<C>, M>),
#[error("Compaction failed: {0}")]
Compaction(Meta<compaction::Error<C>, M>),
#[error("Remote document loading failed: {0}")]
Loading(E),
#[error("Remote context loading failed: {0}")]
ContextLoading(C),
}
impl<M, E, C> CompactError<M, E, C> {
pub fn code(&self) -> ErrorCode {
match self {
Self::Expand(e) => e.code(),
Self::ContextProcessing(e) => e.code(),
Self::Compaction(e) => e.code(),
Self::Loading(_) => ErrorCode::LoadingDocumentFailed,
Self::ContextLoading(_) => ErrorCode::LoadingRemoteContextFailed,
}
}
}
pub type CompactResult<I, M, L> = Result<
json_syntax::MetaValue<M>,
CompactError<M, <L as Loader<I, M>>::Error, <L as ContextLoader<I, M>>::ContextError>,
>;
#[derive(Debug, thiserror::Error)]
pub enum FlattenError<I, B, M, E, C> {
#[error("Expansion failed: {0}")]
Expand(ExpandError<M, E, C>),
#[error("Compaction failed: {0}")]
Compact(CompactError<M, E, C>),
#[error("Conflicting indexes: {0}")]
ConflictingIndexes(ConflictingIndexes<I, B, M>),
#[error("Remote document loading failed: {0}")]
Loading(E),
#[error("Remote context loading failed: {0}")]
ContextLoading(C),
}
impl<I, B, M, E, C> FlattenError<I, B, M, E, C> {
pub fn code(&self) -> ErrorCode {
match self {
Self::Expand(e) => e.code(),
Self::Compact(e) => e.code(),
Self::ConflictingIndexes(_) => ErrorCode::ConflictingIndexes,
Self::Loading(_) => ErrorCode::LoadingDocumentFailed,
Self::ContextLoading(_) => ErrorCode::LoadingRemoteContextFailed,
}
}
}
pub type FlattenResult<I, B, M, L> = Result<
json_syntax::MetaValue<M>,
FlattenError<I, B, M, <L as Loader<I, M>>::Error, <L as ContextLoader<I, M>>::ContextError>,
>;
#[derive(Debug, thiserror::Error)]
pub enum ToRdfError<M, E, C> {
#[error("Expansion failed: {0}")]
Expand(ExpandError<M, E, C>),
}
impl<M, E, C> ToRdfError<M, E, C> {
pub fn code(&self) -> ErrorCode {
match self {
Self::Expand(e) => e.code(),
}
}
}
pub type ToRdfResult<'a, V, M, G, L> = Result<
ToRdf<'a, 'a, V, M, G>,
ToRdfError<
M,
<L as Loader<<V as IriVocabulary>::Iri, M>>::Error,
<L as ContextLoader<<V as IriVocabulary>::Iri, M>>::ContextError,
>,
>;
pub type CompareResult<I, M, L> = Result<
bool,
ExpandError<M, <L as Loader<I, M>>::Error, <L as ContextLoader<I, M>>::ContextError>,
>;
pub trait JsonLdProcessor<I, M> {
fn compare_full<'a, B, C, N, L>(
&'a self,
other: &'a Self,
vocabulary: &'a mut N,
loader: &'a mut L,
options: Options<I, M, C>,
warnings: impl 'a
+ Send
+ context_processing::WarningHandler<N, M>
+ expansion::WarningHandler<B, N, M>,
) -> BoxFuture<CompareResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send;
fn compare_with_using<'a, B, C, N, L>(
&'a self,
other: &'a Self,
vocabulary: &'a mut N,
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<CompareResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.compare_full(other, vocabulary, loader, options, ())
}
fn compare_with<'a, B, N, L>(
&'a self,
other: &'a Self,
vocabulary: &'a mut N,
loader: &'a mut L,
) -> BoxFuture<CompareResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<json_ld_syntax::context::Value<M>>,
L::ContextError: Send,
{
self.compare_with_using(other, vocabulary, loader, Options::default())
}
fn compare_using<'a, B, C, L>(
&'a self,
other: &'a Self,
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<CompareResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
(): Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.compare_with_using(
other,
rdf_types::vocabulary::no_vocabulary_mut(),
loader,
options,
)
}
fn compare<'a, B, L>(
&'a self,
other: &'a Self,
loader: &'a mut L,
) -> BoxFuture<CompareResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
(): Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<json_ld_syntax::context::Value<M>>,
L::ContextError: Send,
{
self.compare_with(other, rdf_types::vocabulary::no_vocabulary_mut(), loader)
}
fn expand_full<'a, B, C, N, L>(
&'a self,
vocabulary: &'a mut N,
loader: &'a mut L,
options: Options<I, M, C>,
warnings: impl 'a
+ Send
+ context_processing::WarningHandler<N, M>
+ expansion::WarningHandler<B, N, M>,
) -> BoxFuture<ExpandResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send;
fn expand_with_using<'a, B, C, N, L>(
&'a self,
vocabulary: &'a mut N,
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<ExpandResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.expand_full(vocabulary, loader, options, ())
}
fn expand_with<'a, B, N, L>(
&'a self,
vocabulary: &'a mut N,
loader: &'a mut L,
) -> BoxFuture<ExpandResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<json_ld_syntax::context::Value<M>>,
L::ContextError: Send,
{
self.expand_with_using(vocabulary, loader, Options::default())
}
fn expand_using<'a, B, C, L>(
&'a self,
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<ExpandResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
(): Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.expand_with_using(vocabulary::no_vocabulary_mut(), loader, options)
}
fn expand<'a, B, L>(&'a self, loader: &'a mut L) -> BoxFuture<ExpandResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
(): Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<json_ld_syntax::context::Value<M>>,
L::ContextError: Send,
{
self.expand_with(vocabulary::no_vocabulary_mut(), loader)
}
fn compact_full<'a, B, C, N, L>(
&'a self,
vocabulary: &'a mut N,
context: RemoteDocumentReference<I, M, C>,
loader: &'a mut L,
options: Options<I, M, C>,
warnings: impl 'a
+ Send
+ context_processing::WarningHandler<N, M>
+ expansion::WarningHandler<B, N, M>,
) -> BoxFuture<'a, CompactResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send;
fn compact_with_using<'a, B, C, N, L>(
&'a self,
vocabulary: &'a mut N,
context: RemoteDocumentReference<I, M, C>,
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<'a, CompactResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.compact_full(vocabulary, context, loader, options, ())
}
fn compact_with<'a, B, C, N, L>(
&'a self,
vocabulary: &'a mut N,
context: RemoteDocumentReference<I, M, C>,
loader: &'a mut L,
) -> BoxFuture<'a, CompactResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.compact_with_using(vocabulary, context, loader, Options::default())
}
fn compact_using<'a, B, C, L>(
&'a self,
context: RemoteDocumentReference<I, M, C>,
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<'a, CompactResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
(): Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.compact_with_using(vocabulary::no_vocabulary_mut(), context, loader, options)
}
fn compact<'a, B, C, L>(
&'a self,
context: RemoteDocumentReference<I, M, C>,
loader: &'a mut L,
) -> BoxFuture<'a, CompactResult<I, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
(): Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.compact_with(vocabulary::no_vocabulary_mut(), context, loader)
}
fn flatten_full<'a, B, C, N, L>(
&'a self,
vocabulary: &'a mut N,
generator: &'a mut (impl Send + Generator<N, M>),
context: Option<RemoteDocumentReference<I, M, C>>,
loader: &'a mut L,
options: Options<I, M, C>,
warnings: impl 'a
+ Send
+ context_processing::WarningHandler<N, M>
+ expansion::WarningHandler<B, N, M>,
) -> BoxFuture<'a, FlattenResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send;
fn flatten_with_using<'a, B, C, N, L>(
&'a self,
vocabulary: &'a mut N,
generator: &'a mut (impl Send + Generator<N, M>),
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<'a, FlattenResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.flatten_full(vocabulary, generator, None, loader, options, ())
}
fn flatten_with<'a, B, N, L>(
&'a self,
vocabulary: &'a mut N,
generator: &'a mut (impl Send + Generator<N, M>),
loader: &'a mut L,
) -> BoxFuture<'a, FlattenResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<json_ld_syntax::context::Value<M>>,
L::ContextError: Send,
{
self.flatten_with_using(vocabulary, generator, loader, Options::default())
}
fn flatten_using<'a, B, C, L>(
&'a self,
generator: &'a mut (impl Send + Generator<(), M>),
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<'a, FlattenResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
(): Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
self.flatten_with_using(vocabulary::no_vocabulary_mut(), generator, loader, options)
}
fn flatten<'a, B, L>(
&'a self,
generator: &'a mut (impl Send + Generator<(), M>),
loader: &'a mut L,
) -> BoxFuture<'a, FlattenResult<I, B, M, L>>
where
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
(): Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<json_ld_syntax::context::Value<M>>,
L::ContextError: Send,
{
self.flatten_with(vocabulary::no_vocabulary_mut(), generator, loader)
}
fn to_rdf_full<'a, B, C, N, G, L>(
&'a self,
vocabulary: &'a mut N,
generator: &'a mut G,
loader: &'a mut L,
options: Options<I, M, C>,
warnings: impl 'a
+ Send
+ context_processing::WarningHandler<N, M>
+ expansion::WarningHandler<B, N, M>,
) -> BoxFuture<ToRdfResult<'a, N, M, G, L>>
where
I: 'a + Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
G: Send + Generator<N, M>,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
Self: Sync,
{
async move {
let rdf_direction = options.rdf_direction;
let produce_generalized_rdf = options.produce_generalized_rdf;
let expanded_input = self
.expand_full(&mut *vocabulary, loader, options.unordered(), warnings)
.await
.map_err(ToRdfError::Expand)?;
Ok(ToRdf::new(
vocabulary,
generator,
expanded_input,
rdf_direction,
produce_generalized_rdf,
))
}
.boxed()
}
fn to_rdf_with_using<'a, B, C, N, G, L>(
&'a self,
vocabulary: &'a mut N,
generator: &'a mut G,
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<ToRdfResult<'a, N, M, G, L>>
where
I: 'a + Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
G: Send + Generator<N, M>,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
Self: Sync,
{
self.to_rdf_full(vocabulary, generator, loader, options, ())
}
fn to_rdf_with<'a, B, N, G, L>(
&'a self,
vocabulary: &'a mut N,
generator: &'a mut G,
loader: &'a mut L,
) -> BoxFuture<ToRdfResult<'a, N, M, G, L>>
where
I: 'a + Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
G: Send + Generator<N, M>,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<json_ld_syntax::context::Value<M>>,
L::ContextError: Send,
Self: Sync,
{
self.to_rdf_full(vocabulary, generator, loader, Options::default(), ())
}
fn to_rdf_using<'a, B, C, G, L>(
&'a self,
generator: &'a mut G,
loader: &'a mut L,
options: Options<I, M, C>,
) -> BoxFuture<ToRdfResult<'a, (), M, G, L>>
where
I: 'a + Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
(): VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
G: Send + Generator<(), M>,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
Self: Sync,
{
self.to_rdf_with_using(
rdf_types::vocabulary::no_vocabulary_mut(),
generator,
loader,
options,
)
}
fn to_rdf<'a, B, G, L>(
&'a self,
generator: &'a mut G,
loader: &'a mut L,
) -> BoxFuture<ToRdfResult<'a, (), M, G, L>>
where
I: 'a + Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
(): VocabularyMut<Iri = I, BlankId = B>,
M: 'a + Clone + Send + Sync,
G: Send + Generator<(), M>,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<json_ld_syntax::context::Value<M>>,
L::ContextError: Send,
Self: Sync,
{
self.to_rdf_using(generator, loader, Options::default())
}
}
pub struct ToRdf<'v, 'g, V: Vocabulary, M, G> {
vocabulary: &'v mut V,
generator: &'g mut G,
doc: Meta<ExpandedDocument<V::Iri, V::BlankId, M>, M>,
rdf_direction: Option<RdfDirection>,
produce_generalized_rdf: bool,
}
impl<'v, 'g, V: Vocabulary, M, G: rdf_types::MetaGenerator<V, M>> ToRdf<'v, 'g, V, M, G> {
fn new(
vocabulary: &'v mut V,
generator: &'g mut G,
mut doc: Meta<ExpandedDocument<V::Iri, V::BlankId, M>, M>,
rdf_direction: Option<RdfDirection>,
produce_generalized_rdf: bool,
) -> Self
where
M: Clone,
V::Iri: Clone + Eq + Hash,
V::BlankId: Clone + Eq + Hash,
{
doc.relabel_and_canonicalize_with(vocabulary, generator);
Self {
vocabulary,
generator,
doc,
rdf_direction,
produce_generalized_rdf,
}
}
pub fn quads<'a: 'v + 'g>(&'a mut self) -> json_ld_core::rdf::Quads<'a, 'v, 'g, V, M, G> {
self.doc.rdf_quads_full(
self.vocabulary,
self.generator,
self.rdf_direction,
self.produce_generalized_rdf,
)
}
#[inline(always)]
pub fn cloned_quads<'a: 'v + 'g>(
&'a mut self,
) -> json_ld_core::rdf::ClonedQuads<'a, 'v, 'g, V, M, G> {
self.quads().cloned()
}
pub fn vocabulary(&self) -> &V {
self.vocabulary
}
pub fn vocabulary_mut(&mut self) -> &mut V {
self.vocabulary
}
pub fn into_vocabulary(self) -> &'v mut V {
self.vocabulary
}
pub fn generator(&self) -> &G {
self.generator
}
pub fn generator_mut(&mut self) -> &mut G {
self.generator
}
pub fn into_generator(self) -> &'g mut G {
self.generator
}
pub fn document(&self) -> &Meta<ExpandedDocument<V::Iri, V::BlankId, M>, M> {
&self.doc
}
pub fn document_mut(&mut self) -> &mut Meta<ExpandedDocument<V::Iri, V::BlankId, M>, M> {
&mut self.doc
}
pub fn into_document(self) -> Meta<ExpandedDocument<V::Iri, V::BlankId, M>, M> {
self.doc
}
}
async fn compact_expanded_full<'a, T, I, B, M, C, N, L>(
expanded_input: &'a Meta<T, M>,
url: Option<&'a I>,
vocabulary: &'a mut N,
context: RemoteDocumentReference<I, M, C>,
loader: &'a mut L,
options: Options<I, M, C>,
warnings: impl Send + context_processing::WarningHandler<N, M>,
) -> Result<json_syntax::MetaValue<M>, CompactError<M, L::Error, L::ContextError>>
where
T: CompactMeta<I, B, M>,
I: Clone + Eq + Hash + Send + Sync,
B: 'a + Clone + Eq + Hash + Send + Sync,
C: 'a + ProcessMeta<I, B, M> + From<json_ld_syntax::context::Value<M>>,
N: Send + Sync + VocabularyMut<Iri = I, BlankId = B>,
M: Clone + Send + Sync,
L: Loader<I, M> + ContextLoader<I, M> + Send + Sync,
L::Output: Into<syntax::Value<M>>,
L::Error: Send,
L::Context: Into<C>,
L::ContextError: Send,
{
let context_base = url.or(options.base.as_ref());
let context = context
.load_context_with(vocabulary, loader)
.await
.map_err(CompactError::ContextLoading)?
.into_document();
let mut active_context: Processed<I, B, C, M> = context
.process_full(
vocabulary,
&Context::new(None),
loader,
context_base.cloned(),
options.context_processing_options(),
warnings,
)
.await
.map_err(CompactError::ContextProcessing)?;
match options.base.as_ref() {
Some(base) => active_context.set_base_iri(Some(base.clone())),
None => {
if options.compact_to_relative && active_context.base_iri().is_none() {
eprintln!("compact to relative");
active_context.set_base_iri(url.cloned());
}
}
}
if let Some(base_iri) = active_context.base_iri() {
eprintln!("base IRI: {}", vocabulary.iri(base_iri).unwrap());
}
expanded_input
.compact_full(
vocabulary,
active_context.as_ref(),
loader,
options.compaction_options(),
)
.await
.map_err(CompactError::Compaction)
}