use crate::{
vocabulary, BlankIdBuf, BlankIdVocabularyMut, Id, Namespace, Vocabulary, VocabularyMut,
};
#[cfg(feature = "meta")]
use locspan::Meta;
pub trait Generator<N: Namespace> {
fn next(&mut self, namespace: &mut N) -> N::Id;
#[cfg(feature = "meta")]
fn with_metadata<M>(self, metadata: M) -> WithMetadata<Self, M>
where
Self: Sized,
{
WithMetadata {
metadata,
generator: self,
}
}
#[cfg(feature = "meta")]
fn with_default_metadata<M: Default>(self) -> WithMetadata<Self, M>
where
Self: Sized,
{
WithMetadata {
metadata: M::default(),
generator: self,
}
}
}
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)
}
}
#[cfg(feature = "meta")]
pub trait MetaGenerator<N: Namespace, M> {
fn next(&mut self, namespace: &mut N) -> Meta<N::Id, 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)
}
}
#[cfg(feature = "meta")]
pub struct WithMetadata<G, M> {
metadata: M,
generator: G,
}
#[cfg(feature = "meta")]
impl<G, M> WithMetadata<G, M> {
pub fn metadata(&self) -> &M {
&self.metadata
}
pub fn generator(&self) -> &G {
&self.generator
}
}
#[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)
}
}
#[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())
}
}
#[derive(Default)]
pub struct Blank {
prefix: String,
count: usize,
}
impl Blank {
pub fn new() -> Self {
Self::new_full(String::new(), 0)
}
pub fn new_with_offset(offset: usize) -> Self {
Self::new_full(String::new(), offset)
}
pub fn new_with_prefix(prefix: String) -> Self {
Self::new_full(prefix, 0)
}
pub fn new_full(prefix: String, offset: usize) -> Self {
Self {
prefix,
count: offset,
}
}
#[cfg(feature = "meta")]
pub fn with_metadata<M>(self, metadata: M) -> WithMetadata<Self, M>
where
Self: Sized,
{
WithMetadata {
metadata,
generator: self,
}
}
#[cfg(feature = "meta")]
pub fn with_default_metadata<M: Default>(self) -> WithMetadata<Self, M>
where
Self: Sized,
{
WithMetadata {
metadata: M::default(),
generator: self,
}
}
pub fn prefix(&self) -> &str {
&self.prefix
}
pub fn count(&self) -> usize {
self.count
}
pub fn next_blank_id(&mut self) -> BlankIdBuf {
let id = unsafe { BlankIdBuf::new_unchecked(format!("_:{}{}", self.prefix, self.count)) };
self.count += 1;
id
}
}
impl<V: Vocabulary + BlankIdVocabularyMut> Generator<V> for Blank {
fn next(&mut self, vocabulary: &mut V) -> Id<V::Iri, V::BlankId> {
Id::Blank(vocabulary.insert_blank_id(&self.next_blank_id()))
}
}
pub enum Uuid {
#[cfg(feature = "uuid-generator-v3")]
V3(uuid::Uuid, String),
#[cfg(feature = "uuid-generator-v4")]
V4,
#[cfg(feature = "uuid-generator-v5")]
V5(uuid::Uuid, String),
}
#[cfg(any(
feature = "uuid-generator-v3",
feature = "uuid-generator-v4",
feature = "uuid-generator-v5"
))]
impl Uuid {
pub fn next_uuid(&self) -> uuid::Uuid {
match self {
#[cfg(feature = "uuid-generator-v3")]
Self::V3(vocabulary, name) => uuid::Uuid::new_v3(vocabulary, name.as_bytes()),
#[cfg(feature = "uuid-generator-v4")]
Self::V4 => uuid::Uuid::new_v4(),
#[cfg(feature = "uuid-generator-v5")]
Self::V5(vocabulary, name) => uuid::Uuid::new_v5(vocabulary, name.as_bytes()),
}
}
#[cfg(feature = "meta")]
pub fn with_metadata<M>(self, metadata: M) -> WithMetadata<Self, M>
where
Self: Sized,
{
WithMetadata {
metadata,
generator: self,
}
}
#[cfg(feature = "meta")]
pub fn with_default_metadata<M: Default>(self) -> WithMetadata<Self, M>
where
Self: Sized,
{
WithMetadata {
metadata: M::default(),
generator: self,
}
}
}
#[cfg(any(
feature = "uuid-generator-v3",
feature = "uuid-generator-v4",
feature = "uuid-generator-v5"
))]
impl<V: crate::Vocabulary + crate::IriVocabularyMut> Generator<V> for Uuid {
fn next(&mut self, vocabulary: &mut V) -> Id<V::Iri, V::BlankId> {
unsafe {
let mut buffer = Vec::with_capacity(uuid::adapter::Urn::LENGTH);
let ptr = buffer.as_mut_ptr();
let capacity = buffer.capacity();
std::mem::forget(buffer);
let uuid = self.next_uuid();
let len = uuid
.to_urn()
.encode_lower(std::slice::from_raw_parts_mut(
ptr,
uuid::adapter::Urn::LENGTH,
))
.len();
let buffer = Vec::from_raw_parts(ptr, len, capacity);
let p = iref::parsing::ParsedIriRef::new(&buffer).unwrap();
let iri = iref::IriBuf::from_raw_parts(buffer, p);
Id::Iri(vocabulary.insert(iri.as_iri()))
}
}
}
#[cfg(any(
feature = "uuid-generator-v3",
feature = "uuid-generator-v4",
feature = "uuid-generator-v5"
))]
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "uuid-generator-v3")]
#[test]
fn uuidv3_iri() {
let mut uuid_gen = Uuid::V3(
uuid::Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8").unwrap(),
"test".to_string(),
);
for _ in 0..100 {
let reference: Id = uuid_gen.next(&mut ());
assert!(iref::IriBuf::new(reference.as_str()).is_ok())
}
}
#[cfg(feature = "uuid-generator-v4")]
#[test]
fn uuidv4_iri() {
let mut uuid_gen = Uuid::V4;
for _ in 0..100 {
let reference: Id = uuid_gen.next(&mut ());
assert!(iref::IriBuf::new(reference.as_str()).is_ok())
}
}
#[cfg(feature = "uuid-generator-v5")]
#[test]
fn uuidv5_iri() {
let mut uuid_gen = Uuid::V5(
uuid::Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8").unwrap(),
"test".to_string(),
);
for _ in 0..100 {
let reference: Id = uuid_gen.next(&mut ());
assert!(iref::IriBuf::new(reference.as_str()).is_ok())
}
}
}
pub struct Unscoped<'a, G>(pub &'a mut G);
impl<'a, 'v, G: Generator<V>, V: VocabularyMut, S> Generator<vocabulary::Scoped<'v, V, S>>
for Unscoped<'a, G>
where
V::BlankId: Clone,
{
fn next(&mut self, vocabulary: &mut vocabulary::Scoped<'v, V, S>) -> Id<V::Iri, V::BlankId> {
self.0.next(vocabulary.inner)
}
}