rsonpath/result/
approx_span.rs1use super::{output_queue::OutputQueue, *};
6use std::cell::RefCell;
7
8pub struct ApproxSpanRecorder<'s, S> {
11 internal: RefCell<InternalRecorder<'s, S>>,
12}
13
14struct InternalRecorder<'s, S> {
15 sink: &'s mut S,
16 leading_padding_len: usize,
17 match_count: usize,
18 stack: Vec<PartialNode>,
19 output_queue: OutputQueue<MatchSpan>,
20}
21
22struct PartialNode {
23 id: usize,
24 start_idx: MatchIndex,
25 start_depth: Depth,
26 ty: MatchedNodeType,
27}
28
29impl<'s, S> ApproxSpanRecorder<'s, S> {
30 #[inline]
31 pub(crate) fn new(sink: &'s mut S, leading_padding_len: usize) -> Self {
32 Self {
33 internal: RefCell::new(InternalRecorder::new(sink, leading_padding_len)),
34 }
35 }
36}
37
38impl<B: Deref<Target = [u8]>, S> InputRecorder<B> for ApproxSpanRecorder<'_, S>
39where
40 S: Sink<MatchSpan>,
41{
42 #[inline(always)]
43 fn record_block_start(&self, _new_block: B) {
44 }
46}
47
48impl<B: Deref<Target = [u8]>, S> Recorder<B> for ApproxSpanRecorder<'_, S>
49where
50 S: Sink<MatchSpan>,
51{
52 #[inline]
53 fn record_match(&self, idx: usize, depth: Depth, ty: MatchedNodeType) -> Result<(), EngineError> {
54 self.internal.borrow_mut().record_start(idx, depth, ty);
55 Ok(())
56 }
57
58 #[inline]
59 fn record_value_terminator(&self, idx: usize, depth: Depth) -> Result<(), EngineError> {
60 self.internal.borrow_mut().record_end(idx, depth)
61 }
62}
63
64impl<'s, S> InternalRecorder<'s, S> {
65 fn new(sink: &'s mut S, leading_padding_len: usize) -> Self {
66 Self {
67 sink,
68 leading_padding_len,
69 stack: vec![],
70 match_count: 0,
71 output_queue: OutputQueue::new(),
72 }
73 }
74}
75
76impl<S> InternalRecorder<'_, S>
77where
78 S: Sink<MatchSpan>,
79{
80 fn record_start(&mut self, start_idx: usize, start_depth: Depth, ty: MatchedNodeType) {
81 self.stack.push(PartialNode {
82 id: self.match_count,
83 start_idx,
84 start_depth,
85 ty,
86 });
87 self.match_count += 1;
88 }
89
90 fn record_end(&mut self, idx: usize, depth: Depth) -> Result<(), EngineError> {
91 while let Some(node) = self.stack.last() {
92 if node.start_depth >= depth {
93 let node = self.stack.pop().expect("last was Some, pop must succeed");
94 let end_idx = if node.ty == MatchedNodeType::Complex {
95 idx + 1
96 } else {
97 idx
98 };
99 let span = MatchSpan {
100 start_idx: node.start_idx - self.leading_padding_len,
101 len: end_idx - node.start_idx,
102 };
103 self.output_queue.insert(node.id, span);
104 } else {
105 break;
106 }
107 }
108
109 if self.stack.is_empty() {
110 self.output_queue
111 .output_to(self.sink)
112 .map_err(|err| EngineError::SinkError(Box::new(err)))?;
113 }
114
115 Ok(())
116 }
117}