Skip to main content

linked_data/de/
replay.rs

1use rdf_syntax::{IndexedBTreeDataset, Quad, Term};
2
3use crate::LinkedDataDeserializer;
4
5pub struct ReplayDeserializer<D, R = Term> {
6	inner: D,
7	pending_quads: IndexedBTreeDataset<R>,
8	pending_resources: Vec<R>,
9	visited_quads: Vec<Quad<R>>,
10	visited_resources: Vec<R>,
11}
12
13impl<D, R> ReplayDeserializer<D, R> {
14	pub fn new(inner: D) -> Self {
15		Self {
16			inner,
17			pending_quads: IndexedBTreeDataset::new(),
18			pending_resources: Vec::new(),
19			visited_quads: Vec::new(),
20			visited_resources: Vec::new(),
21		}
22	}
23}
24
25impl<D, R> ReplayDeserializer<D, R>
26where
27	R: Clone + Ord,
28{
29	pub fn reset(&mut self) {
30		self.pending_quads.extend(self.visited_quads.drain(..));
31		self.pending_resources
32			.extend(self.visited_resources.drain(..).rev());
33	}
34}
35
36impl<R: Clone + Ord, D: LinkedDataDeserializer<R>> LinkedDataDeserializer<R>
37	for ReplayDeserializer<D, R>
38{
39	type Error = D::Error;
40
41	fn interpret(&mut self, term: rdf_syntax::CowTerm) -> Result<R, Self::Error> {
42		self.inner.interpret(term)
43	}
44
45	fn terms_of<'r>(
46		&'r self,
47		resource: &'r R,
48	) -> Result<impl Iterator<Item = Result<rdf_syntax::CowTerm<'r>, Self::Error>>, Self::Error> {
49		self.inner.terms_of(resource)
50	}
51
52	fn peek_resources<'a>(
53		&'a self,
54	) -> Result<impl Iterator<Item = Result<&'a R, Self::Error>>, Self::Error>
55	where
56		R: 'a,
57	{
58		Ok(self
59			.pending_resources
60			.iter()
61			.rev()
62			.map(Ok)
63			.chain(self.inner.peek_resources()?))
64	}
65
66	fn deserialize_resource(&mut self, resource: Option<R>) -> Result<Option<R>, Self::Error> {
67		let resource = match self.pending_resources.pop() {
68			Some(a) => match resource {
69				Some(b) => {
70					if a == b {
71						Some(a)
72					} else {
73						self.pending_resources.push(a);
74						return Err(crate::de::Error::unexpected_resource(&b));
75					}
76				}
77				None => Some(a),
78			},
79			None => self.inner.deserialize_resource(resource)?,
80		};
81
82		if let Some(r) = resource.clone() {
83			self.visited_resources.push(r);
84		}
85
86		Ok(resource)
87	}
88
89	fn deserialize_quad<'p>(
90		&mut self,
91		pattern: impl Into<rdf_syntax::pattern::LinearQuadPattern<&'p R>>,
92	) -> Result<Option<rdf_syntax::Quad<R>>, Self::Error>
93	where
94		R: 'p,
95	{
96		let pattern = pattern.into();
97		let quad = match self.pending_quads.extract_pattern_matching(pattern).next() {
98			Some(quad) => Some(quad),
99			None => self.inner.deserialize_quad(pattern)?,
100		};
101
102		if let Some(quad) = quad.clone() {
103			self.visited_quads.push(quad);
104		}
105
106		Ok(quad)
107	}
108
109	fn peek_quads<'p>(
110		&'p self,
111		pattern: impl Into<rdf_syntax::pattern::LinearQuadPattern<&'p R>>,
112	) -> Result<impl Iterator<Item = Result<Quad<&'p R>, Self::Error>>, Self::Error>
113	where
114		R: 'p,
115	{
116		let pattern = pattern.into();
117		Ok(self
118			.pending_quads
119			.pattern_matching(pattern)
120			.map(Ok)
121			.chain(self.inner.peek_quads(pattern)?))
122	}
123}