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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::ops::Deref;
use std::{borrow::Borrow, hash::Hash};

use iref::IriBuf;
use linked_data::{LinkedData, LinkedDataGraph, LinkedDataResource, LinkedDataSubject};
use rdf_types::{vocabulary::IriVocabularyMut, BlankIdBuf, Interpretation, Vocabulary};

pub mod expanded;
pub mod flattened;

pub use expanded::ExpandedDocument;
pub use flattened::FlattenedDocument;

use crate::RemoteDocument;

/// JSON-LD document in both compact and expanded form.
#[derive(Debug, Clone)]
pub struct Document<I = IriBuf, B = BlankIdBuf> {
	remote: RemoteDocument<I>,
	expanded: ExpandedDocument<I, B>,
}

impl<I, B> Document<I, B> {
	pub fn new(remote: RemoteDocument<I>, expanded: ExpandedDocument<I, B>) -> Self {
		Self { remote, expanded }
	}

	pub fn into_remote(self) -> RemoteDocument<I> {
		self.remote
	}

	pub fn into_compact(self) -> json_ld_syntax::Value {
		self.remote.into_document()
	}

	pub fn into_expanded(self) -> ExpandedDocument<I, B> {
		self.expanded
	}

	#[allow(clippy::type_complexity)]
	pub fn into_parts(self) -> (RemoteDocument<I>, ExpandedDocument<I, B>) {
		(self.remote, self.expanded)
	}

	pub fn as_remote(&self) -> &RemoteDocument<I> {
		&self.remote
	}

	pub fn as_compact(&self) -> &json_ld_syntax::Value {
		self.remote.document()
	}

	pub fn as_expanded(&self) -> &ExpandedDocument<I, B> {
		&self.expanded
	}
}

impl<I, B> Deref for Document<I, B> {
	type Target = ExpandedDocument<I, B>;

	fn deref(&self) -> &Self::Target {
		&self.expanded
	}
}

impl<I, B> Borrow<RemoteDocument<I>> for Document<I, B> {
	fn borrow(&self) -> &RemoteDocument<I> {
		&self.remote
	}
}

impl<I, B> Borrow<json_ld_syntax::Value> for Document<I, B> {
	fn borrow(&self) -> &json_ld_syntax::Value {
		self.remote.document()
	}
}

impl<I, B> Borrow<ExpandedDocument<I, B>> for Document<I, B> {
	fn borrow(&self) -> &ExpandedDocument<I, B> {
		&self.expanded
	}
}

impl<I: Eq + Hash, B: Eq + Hash> PartialEq for Document<I, B> {
	fn eq(&self, other: &Self) -> bool {
		self.expanded.eq(&other.expanded)
	}
}

impl<I: Eq + Hash, B: Eq + Hash> Eq for Document<I, B> {}

#[cfg(feature = "serde")]
impl<I, B> serde::Serialize for Document<I, B> {
	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
	where
		S: serde::Serializer,
	{
		self.remote.document().serialize(serializer)
	}
}

impl<V: Vocabulary, I: Interpretation> LinkedData<I, V> for Document<V::Iri, V::BlankId>
where
	V: IriVocabularyMut,
	V::Iri: LinkedDataSubject<I, V> + LinkedDataResource<I, V>,
	V::BlankId: LinkedDataSubject<I, V> + LinkedDataResource<I, V>,
{
	fn visit<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
	where
		S: linked_data::Visitor<I, V>,
	{
		self.expanded.visit(visitor)
	}
}

impl<V: Vocabulary, I: Interpretation> LinkedDataGraph<I, V> for Document<V::Iri, V::BlankId>
where
	V: IriVocabularyMut,
	V::Iri: LinkedDataSubject<I, V> + LinkedDataResource<I, V>,
	V::BlankId: LinkedDataSubject<I, V> + LinkedDataResource<I, V>,
{
	fn visit_graph<S>(&self, visitor: S) -> Result<S::Ok, S::Error>
	where
		S: linked_data::GraphVisitor<I, V>,
	{
		self.expanded.visit_graph(visitor)
	}
}