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}