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
use crate::{syntax::TermLike, util};
use iref::{AsIri, Iri, IriBuf};
use json::JsonValue;
use std::hash::Hash;
/// Unique identifier types.
///
/// While JSON-LD uses [Internationalized Resource Identifiers (IRIs)](https://en.wikipedia.org/wiki/Internationalized_resource_identifier)
/// to uniquely identify each node,
/// this crate does not imposes the internal representation of identifiers.
///
/// Whatever type you choose, it must implement this trait to usure that:
/// - there is a low cost bijection with IRIs,
/// - it can be cloned ([`Clone`]),
/// - it can be compared ([`PartialEq`], [`Eq`]),
/// - it can be hashed ([`Hash`]).
///
/// # Using `enum` types
/// If you know in advance which IRIs will be used by your implementation,
/// one possibility is to use a `enum` type as identifier.
/// This can be done throught the use of the [`Lexicon`](`crate::Lexicon`) type along with the
/// [`iref-enum`](https://crates.io/crates/iref-enum) crate:
/// ```
/// use iref_enum::*;
/// use json_ld::Lexicon;
///
/// /// Vocabulary used in the implementation.
/// #[derive(IriEnum, Clone, Copy, PartialEq, Eq, Hash)]
/// #[iri_prefix("rdfs" = "http://www.w3.org/2000/01/rdf-schema#")]
/// #[iri_prefix("manifest" = "http://www.w3.org/2001/sw/DataAccess/tests/test-manifest#")]
/// #[iri_prefix("vocab" = "https://w3c.github.io/json-ld-api/tests/vocab#")]
/// pub enum Vocab {
/// #[iri("rdfs:comment")] Comment,
///
/// #[iri("manifest:name")] Name,
/// #[iri("manifest:entries")] Entries,
/// #[iri("manifest:action")] Action,
/// #[iri("manifest:result")] Result,
///
/// #[iri("vocab:PositiveEvaluationTest")] PositiveEvalTest,
/// #[iri("vocab:NegativeEvaluationTest")] NegativeEvalTest,
/// #[iri("vocab:option")] Option,
/// #[iri("vocab:specVersion")] SpecVersion,
/// #[iri("vocab:processingMode")] ProcessingMode,
/// #[iri("vocab:expandContext")] ExpandContext,
/// #[iri("vocab:base")] Base
/// }
///
/// /// A fully functional identifier type.
/// pub type Id = Lexicon<Vocab>;
///
/// fn handle_node(node: &json_ld::Node<Id>) {
/// for name in node.get(Vocab::Name) { // <- note that we can directly use `Vocab` here.
/// println!("node name: {}", name.as_str().unwrap());
/// }
/// }
/// ```
pub trait Id: AsIri + Clone + PartialEq + Eq + Hash {
/// Create an identifier from its IRI.
fn from_iri(iri: Iri) -> Self;
}
impl Id for IriBuf {
fn from_iri(iri: Iri) -> IriBuf {
iri.into()
}
}
impl<T: Id> TermLike for T {
fn as_str(&self) -> &str {
self.as_iri().into_str()
}
fn as_iri(&self) -> Option<Iri> {
Some(self.as_iri())
}
}
impl<T: Id> util::AsJson for T {
fn as_json(&self) -> JsonValue {
self.as_iri().as_str().into()
}
}