Skip to content

Commit

Permalink
Add interpretation::WithVocabulary
Browse files Browse the repository at this point in the history
Add `vocabulary: V` type parameter to `InterpretationMut`.
Remove `Namespace` trait.
Change return type of `Generator<V>::next` to `Id<V::Iri, V::BlankId>`.
  • Loading branch information
timothee-haudebourg committed Oct 18, 2023
1 parent d7a55ad commit ade35fd
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 41 deletions.
41 changes: 23 additions & 18 deletions src/generator.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use crate::{
vocabulary, BlankIdBuf, BlankIdVocabularyMut, Id, Namespace, Vocabulary, VocabularyMut,
vocabulary, BlankIdBuf, BlankIdVocabulary, BlankIdVocabularyMut, Id, IriVocabulary, Vocabulary,
VocabularyMut,
};

#[cfg(feature = "meta")]
use locspan::Meta;

/// Subject identifier generator.
pub trait Generator<N: Namespace> {
/// Generates the next fresh identifier in the given namespace.
fn next(&mut self, namespace: &mut N) -> N::Id;
pub trait Generator<V: IriVocabulary + BlankIdVocabulary> {
/// Generates the next fresh node identifier in the given vocabulary.
fn next(&mut self, vocabulary: &mut V) -> Id<V::Iri, V::BlankId>;

#[cfg(feature = "meta")]
/// Generates identifiers annotated with the given metadata.
Expand All @@ -35,22 +36,24 @@ pub trait Generator<N: Namespace> {
}
}

impl<'a, N: Namespace, G: Generator<N>> Generator<N> for &'a mut G {
fn next(&mut self, namespace: &mut N) -> N::Id {
(*self).next(namespace)
impl<'a, V: IriVocabulary + BlankIdVocabulary, G: Generator<V>> Generator<V> for &'a mut G {
fn next(&mut self, vocabulary: &mut V) -> Id<V::Iri, V::BlankId> {
(*self).next(vocabulary)
}
}

#[cfg(feature = "meta")]
/// Subject identifier generator, with metadata.
pub trait MetaGenerator<N: Namespace, M> {
fn next(&mut self, namespace: &mut N) -> Meta<N::Id, M>;
pub trait MetaGenerator<V: IriVocabulary + BlankIdVocabulary, M> {
fn next(&mut self, vocabulary: &mut V) -> Meta<Id<V::Iri, V::BlankId>, M>;
}

#[cfg(feature = "meta")]
impl<'a, N: Namespace, M, G: MetaGenerator<N, M>> MetaGenerator<N, M> for &'a mut G {
fn next(&mut self, namespace: &mut N) -> Meta<N::Id, M> {
(*self).next(namespace)
impl<'a, V: IriVocabulary + BlankIdVocabulary, M, G: MetaGenerator<V, M>> MetaGenerator<V, M>
for &'a mut G
{
fn next(&mut self, vocabulary: &mut V) -> Meta<Id<V::Iri, V::BlankId>, M> {
(*self).next(vocabulary)
}
}

Expand All @@ -72,16 +75,18 @@ impl<G, M> WithMetadata<G, M> {
}

#[cfg(feature = "meta")]
impl<N: Namespace, G: Generator<N>, M> Generator<N> for WithMetadata<G, M> {
fn next(&mut self, namespace: &mut N) -> N::Id {
self.generator.next(namespace)
impl<V: IriVocabulary + BlankIdVocabulary, G: Generator<V>, M> Generator<V> for WithMetadata<G, M> {
fn next(&mut self, vocabulary: &mut V) -> Id<V::Iri, V::BlankId> {
self.generator.next(vocabulary)
}
}

#[cfg(feature = "meta")]
impl<N: Namespace, G: Generator<N>, M: Clone> MetaGenerator<N, M> for WithMetadata<G, M> {
fn next(&mut self, namespace: &mut N) -> Meta<N::Id, M> {
Meta(self.generator.next(namespace), self.metadata.clone())
impl<V: IriVocabulary + BlankIdVocabulary, G: Generator<V>, M: Clone> MetaGenerator<V, M>
for WithMetadata<G, M>
{
fn next(&mut self, vocabulary: &mut V) -> Meta<Id<V::Iri, V::BlankId>, M> {
Meta(self.generator.next(vocabulary), self.metadata.clone())
}
}

Expand Down
19 changes: 11 additions & 8 deletions src/interpretation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ use langtag::LanguageTagBuf;
use crate::{
literal, BlankId, BlankIdBuf, BlankIdVocabulary, BlankIdVocabularyMut, Generator, Id,
IriVocabulary, IriVocabularyMut, LanguageTagVocabularyMut, Literal, LiteralVocabulary,
LiteralVocabularyMut, Namespace, Quad, Term,
LiteralVocabularyMut, Quad, Term,
};

mod indexed;
mod none;
mod with_generator;

pub use indexed::*;
pub use with_generator::WithGenerator;

pub type UninterpretedIdRef<'a, I> =
Id<&'a <I as ReverseIriInterpretation>::Iri, &'a <I as ReverseBlankIdInterpretation>::BlankId>;
Expand Down Expand Up @@ -206,9 +208,9 @@ impl<V: LiteralVocabulary, I: LexicalIdInterpretation<V> + LiteralInterpretation
}

/// Mutable RDF resource interpretation.
pub trait InterpretationMut: Interpretation {
pub trait InterpretationMut<V>: Interpretation {
/// Creates a new resource.
fn new_resource(&mut self) -> Self::Resource;
fn new_resource(&mut self, vocabulary: &mut V) -> Self::Resource;
}

/// Mutable IRI interpretation.
Expand Down Expand Up @@ -889,14 +891,15 @@ pub trait ReverseTermInterpretationMut:

/// Generates and assign a node identifier for all the resources that don't
/// have any term, using the given generator.
fn generate_ids<N: Namespace<Id = Id<Self::Iri, Self::BlankId>>>(
fn generate_ids<V: IriVocabulary + BlankIdVocabulary>(
&mut self,
namespace: &mut N,
generator: &mut impl Generator<N>,
vocabulary: &mut V,
generator: &mut impl Generator<V>,
) where
Self: TraversableInterpretation + ReverseTermInterpretationMut,
Self: TraversableInterpretation
+ ReverseTermInterpretationMut<Iri = V::Iri, BlankId = V::BlankId>,
{
self.assign_terms(|i, r| (!i.has_term(r)).then(|| Term::Id(generator.next(namespace))))
self.assign_terms(|i, r| (!i.has_term(r)).then(|| Term::Id(generator.next(vocabulary))))
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/interpretation/indexed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ impl TraversableInterpretation for Indexed {
}
}

impl InterpretationMut for Indexed {
fn new_resource(&mut self) -> Self::Resource {
impl<V> InterpretationMut<V> for Indexed {
fn new_resource(&mut self, _vocabulary: &mut V) -> Self::Resource {
self.resources.insert().0
}
}
Expand Down
155 changes: 155 additions & 0 deletions src/interpretation/with_generator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use crate::{
BlankIdInterpretation, BlankIdInterpretationMut, BlankIdVocabulary, Generator, Id,
Interpretation, InterpretationMut, IriInterpretation, IriInterpretationMut, IriVocabulary,
LiteralInterpretation, LiteralInterpretationMut, ReverseBlankIdInterpretation,
ReverseBlankIdInterpretationMut, ReverseIriInterpretation, ReverseIriInterpretationMut,
ReverseLiteralInterpretation, ReverseLiteralInterpretationMut,
};

/// Combines any RDF interpretation with a node id generator to make it
/// implement `InterpretationMut`.
///
/// # Use cases
///
/// ## `()` does not implement `InterpretationMut`
///
/// The transparent interpretation (the unit type `()`) does not implement
/// `InterpretationMut` because the `new_resource` method would require the
/// creation of a fresh, unused, blank node identifier, which the transparent
/// interpretation cannot create without a node id generator.
///
/// ## Resources returned by `InterpretationMut::new_resource` have no lexical representation
///
/// Interpreted resources are not required to have a lexical representation.
/// This is most probably the case for new resources returned by
/// `InterpretationMut::new_resource`. You can use `WithGenerator` to pair the
/// interpretation with a node id generator so that `new_resource` will assign
/// a lexical representation to new resources (a fresh blank node id for
/// instance).
pub struct WithGenerator<'a, I, G> {
interpretation: &'a mut I,
generator: G,
}

impl<'a, I, G> WithGenerator<'a, I, G> {
pub fn new(interpretation: &'a mut I, generator: G) -> Self {
Self {
interpretation,
generator,
}
}
}

impl<'a, I: Interpretation, G> Interpretation for WithGenerator<'a, I, G> {
type Resource = I::Resource;
}

impl<'a, V: IriVocabulary + BlankIdVocabulary, I, G: Generator<V>> InterpretationMut<V>
for WithGenerator<'a, I, G>
where
I: IriInterpretationMut<V::Iri> + BlankIdInterpretationMut<V::BlankId>,
{
fn new_resource(&mut self, vocabulary: &mut V) -> Self::Resource {
match self.generator.next(vocabulary) {
Id::Iri(i) => self.interpretation.interpret_iri(i),
Id::Blank(b) => self.interpretation.interpret_blank_id(b),
}
}
}

impl<'a, Iri, I: IriInterpretation<Iri>, G> IriInterpretation<Iri> for WithGenerator<'a, I, G> {
fn iri_interpretation(&self, iri: &Iri) -> Option<Self::Resource> {
self.interpretation.iri_interpretation(iri)
}
}

impl<'a, Iri, I: IriInterpretationMut<Iri>, G> IriInterpretationMut<Iri>
for WithGenerator<'a, I, G>
{
fn interpret_iri(&mut self, iri: Iri) -> Self::Resource {
self.interpretation.interpret_iri(iri)
}
}

impl<'i, I: ReverseIriInterpretation, G> ReverseIriInterpretation for WithGenerator<'i, I, G> {
type Iri = I::Iri;
type Iris<'a> = I::Iris<'a> where Self: 'a;

fn iris_of<'a>(&'a self, id: &'a Self::Resource) -> Self::Iris<'a> {
self.interpretation.iris_of(id)
}
}

impl<'i, I: ReverseIriInterpretationMut, G> ReverseIriInterpretationMut
for WithGenerator<'i, I, G>
{
fn assign_iri(&mut self, id: Self::Resource, iri: Self::Iri) -> bool {
self.interpretation.assign_iri(id, iri)
}
}

impl<'a, B, I: BlankIdInterpretation<B>, G> BlankIdInterpretation<B> for WithGenerator<'a, I, G> {
fn blank_id_interpretation(&self, blank_id: &B) -> Option<Self::Resource> {
self.interpretation.blank_id_interpretation(blank_id)
}
}

impl<'a, B, I: BlankIdInterpretationMut<B>, G> BlankIdInterpretationMut<B>
for WithGenerator<'a, I, G>
{
fn interpret_blank_id(&mut self, blank_id: B) -> Self::Resource {
self.interpretation.interpret_blank_id(blank_id)
}
}

impl<'i, I: ReverseBlankIdInterpretation, G> ReverseBlankIdInterpretation
for WithGenerator<'i, I, G>
{
type BlankId = I::BlankId;
type BlankIds<'a> = I::BlankIds<'a> where Self: 'a;

fn blank_ids_of<'a>(&'a self, id: &'a Self::Resource) -> Self::BlankIds<'a> {
self.interpretation.blank_ids_of(id)
}
}

impl<'i, I: ReverseBlankIdInterpretationMut, G> ReverseBlankIdInterpretationMut
for WithGenerator<'i, I, G>
{
fn assign_blank_id(&mut self, id: Self::Resource, blank_id: Self::BlankId) -> bool {
self.interpretation.assign_blank_id(id, blank_id)
}
}

impl<'a, L, I: LiteralInterpretation<L>, G> LiteralInterpretation<L> for WithGenerator<'a, I, G> {
fn literal_interpretation(&self, literal: &L) -> Option<Self::Resource> {
self.interpretation.literal_interpretation(literal)
}
}

impl<'a, L, I: LiteralInterpretationMut<L>, G> LiteralInterpretationMut<L>
for WithGenerator<'a, I, G>
{
fn interpret_literal(&mut self, literal: L) -> Self::Resource {
self.interpretation.interpret_literal(literal)
}
}

impl<'i, I: ReverseLiteralInterpretation, G> ReverseLiteralInterpretation
for WithGenerator<'i, I, G>
{
type Literal = I::Literal;
type Literals<'a> = I::Literals<'a> where Self: 'a;

fn literals_of<'a>(&'a self, id: &'a Self::Resource) -> Self::Literals<'a> {
self.interpretation.literals_of(id)
}
}

impl<'i, I: ReverseLiteralInterpretationMut, G> ReverseLiteralInterpretationMut
for WithGenerator<'i, I, G>
{
fn assign_literal(&mut self, resource: Self::Resource, literal: Self::Literal) -> bool {
self.interpretation.assign_literal(resource, literal)
}
}
11 changes: 4 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ pub use interpretation::{
Interpret, Interpretation, InterpretationMut, IriInterpretation, IriInterpretationMut,
LexicalIdInterpretation, LexicalIdInterpretationMut, LexicalTermInterpretation,
LexicalTermInterpretationMut, LiteralInterpretation, LiteralInterpretationMut,
ReverseIdInterpretation, ReverseLiteralInterpretation, ReverseTermInterpretation,
ReverseTermInterpretationMut, TermInterpretation, TermInterpretationMut,
ReverseBlankIdInterpretation, ReverseBlankIdInterpretationMut, ReverseIdInterpretation,
ReverseIriInterpretation, ReverseIriInterpretationMut, ReverseLiteralInterpretation,
ReverseLiteralInterpretationMut, ReverseTermInterpretation, ReverseTermInterpretationMut,
TermInterpretation, TermInterpretationMut,
};
use iref::Iri;
pub use literal::{
Expand All @@ -52,8 +54,3 @@ pub const XSD_STRING: &Iri = static_iref::iri!("http://www.w3.org/2001/XMLSchema

#[cfg(feature = "meta")]
pub use generator::MetaGenerator;

/// Node identifier namespace.
pub trait Namespace {
type Id;
}
7 changes: 1 addition & 6 deletions src/vocabulary.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{BlankId, BlankIdBuf, Id, Literal, Namespace};
use crate::{BlankId, BlankIdBuf, Literal};
use iref::{Iri, IriBuf};

mod indexed;
Expand Down Expand Up @@ -38,11 +38,6 @@ impl<V: IriVocabulary + BlankIdVocabulary + LiteralVocabulary + LanguageTagVocab
{
}

/// Any vocabulary is also a namespace.
impl<V: Vocabulary> Namespace for V {
type Id = Id<V::Iri, V::BlankId>;
}

impl<
V: IriVocabularyMut + BlankIdVocabularyMut + LiteralVocabularyMut + LanguageTagVocabularyMut,
> VocabularyMut for V
Expand Down

0 comments on commit ade35fd

Please sign in to comment.