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
//! This crate implements JSON-LD serialization (from RDF dataset to JSON-LD)
//! through the [`linked_data`](https://github.com/spruceid/linked-data-rs)
//! crate.
//! The input value can be an RDF dataset, or any type implementing
//! [`linked_data::LinkedData`].
use std::hash::Hash;

use json_ld_core::{ExpandedDocument, Node, Object};

use linked_data::{rdf_types::Vocabulary, LinkedData, LinkedDataResource, LinkedDataSubject};
use rdf_types::{
	interpretation::{
		ReverseBlankIdInterpretation, ReverseIriInterpretation, ReverseLiteralInterpretation,
	},
	vocabulary::IriVocabularyMut,
	Interpretation,
};

mod expanded;

use expanded::SerializeExpandedDocument;

pub use expanded::{serialize_node_with, serialize_object_with};

#[derive(Debug, thiserror::Error)]
pub enum Error {
	#[error("invalid graph label")]
	InvalidGraph,

	#[error("invalid predicate")]
	InvalidPredicate,

	#[error("invalid node object")]
	InvalidNode,

	#[error("reverse properties on lists are not supported")]
	ListReverseProperty,

	#[error("included nodes on lists are not supported")]
	ListInclude,
}

/// Serialize the given Linked-Data value into a JSON-LD document.
pub fn serialize(value: &impl LinkedData) -> Result<ExpandedDocument, Error> {
	serialize_with(&mut (), &mut (), value)
}

/// Serialize the given Linked-Data value into a JSON-LD document using a
/// custom vocabulary and interpretation.
pub fn serialize_with<V, I>(
	vocabulary: &mut V,
	interpretation: &mut I,
	value: &impl LinkedData<I, V>,
) -> Result<ExpandedDocument<V::Iri, V::BlankId>, Error>
where
	V: Vocabulary + IriVocabularyMut,
	V::Iri: Clone + Eq + Hash,
	V::BlankId: Clone + Eq + Hash,
	I: Interpretation
		+ ReverseIriInterpretation<Iri = V::Iri>
		+ ReverseBlankIdInterpretation<BlankId = V::BlankId>
		+ ReverseLiteralInterpretation<Literal = V::Literal>,
{
	let serializer = SerializeExpandedDocument::new(vocabulary, interpretation);

	value.visit(serializer)
}

/// Serialize the given Linked-Data value into a JSON-LD object.
pub fn serialize_object(
	value: &(impl LinkedDataSubject + LinkedDataResource),
) -> Result<Object, Error> {
	serialize_object_with(&mut (), &mut (), value)
}

/// Serialize the given Linked-Data value into a JSON-LD node object.
pub fn serialize_node(
	value: &(impl LinkedDataSubject + LinkedDataResource),
) -> Result<Node, Error> {
	serialize_node_with(&mut (), &mut (), value)
}