1use crate::debug::tracks::debug_tracks;
2use crate::{Code, DynTrackProvider};
3use nom::{AsBytes, InputIter, InputLength, InputTake, Offset, Slice};
4use nom_locate::LocatedSpan;
5use std::cell::RefCell;
6use std::fmt::{Debug, Formatter};
7use std::ops::{RangeFrom, RangeTo};
8
9#[derive(Debug)]
11pub enum TrackData<C, T>
12where
13 C: Code,
14{
15 Enter(C, LocatedSpan<T, ()>),
17 Exit(),
19 Ok(LocatedSpan<T, ()>, LocatedSpan<T, ()>),
21 Err(LocatedSpan<T, ()>, C, String),
23 Warn(LocatedSpan<T, ()>, &'static str),
25 Info(LocatedSpan<T, ()>, &'static str),
27 Debug(LocatedSpan<T, ()>, String),
29}
30
31pub trait TrackProvider<C, T>
33where
34 C: Code,
35{
36 fn track_span<'s>(&'s self, text: T) -> LocatedSpan<T, DynTrackProvider<'s, C, T>>
38 where
39 T: 's;
40
41 fn results(&self) -> TrackedDataVec<C, T>;
44
45 fn track(&self, data: TrackData<C, T>);
47}
48
49impl<'c, C, T> Debug for DynTrackProvider<'c, C, T>
50where
51 C: Code,
52{
53 fn fmt(&self, _: &mut Formatter<'_>) -> std::fmt::Result {
54 Ok(())
55 }
56}
57
58#[derive(Debug)]
59pub struct TrackedData<C, I>
60where
61 C: Code,
62{
63 pub func: C,
64 pub callstack: Vec<C>,
65 pub track: TrackData<C, I>,
66}
67
68pub struct TrackedDataVec<C, I>(Vec<TrackedData<C, I>>)
69where
70 C: Code;
71
72impl<C, I> Debug for TrackedDataVec<C, I>
73where
74 C: Code,
75 I: AsBytes + Clone + Debug,
76 I: Offset
77 + InputTake
78 + InputIter
79 + InputLength
80 + Slice<RangeFrom<usize>>
81 + Slice<RangeTo<usize>>,
82{
83 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84 debug_tracks(f, f.width().into(), &self.0)
85 }
86}
87
88#[derive(Debug)]
89pub struct StdTracker<C, T>
90where
91 T: AsBytes + Clone,
92 C: Code,
93{
94 data: RefCell<StdTracks<C, T>>,
95}
96
97#[derive(Debug)]
98struct StdTracks<C, T>
99where
100 T: AsBytes + Clone,
101 C: Code,
102{
103 func: Vec<C>,
104 track: Vec<TrackedData<C, T>>,
105}
106
107impl<C, T> StdTracker<C, T>
108where
109 T: AsBytes + Clone,
110 C: Code,
111{
112 pub fn new() -> Self {
114 Self {
115 data: Default::default(),
116 }
117 }
118
119 fn push_func(&self, func: C) {
121 self.data.borrow_mut().func.push(func);
122 }
123
124 fn pop_func(&self) {
126 self.data.borrow_mut().func.pop();
127 }
128
129 fn func(&self) -> C {
131 *self
132 .data
133 .borrow()
134 .func
135 .last()
136 .expect("Vec<FnCode> is empty. forgot to trace.enter()")
137 }
138
139 fn callstack(&self) -> Vec<C> {
140 self.data.borrow().func.clone()
141 }
142
143 fn append_track(&self, track: TrackData<C, T>) {
144 let callstack = self.callstack();
145 let func = self.func();
146 self.data.borrow_mut().track.push(TrackedData {
147 func,
148 callstack,
149 track,
150 });
151 }
152}
153
154impl<C, T> TrackProvider<C, T> for StdTracker<C, T>
155where
156 T: AsBytes + Clone,
157 C: Code,
158{
159 fn track_span<'s>(&'s self, text: T) -> LocatedSpan<T, DynTrackProvider<'s, C, T>>
161 where
162 T: 's,
163 {
164 LocatedSpan::new_extra(text, self)
165 }
166
167 fn results(&self) -> TrackedDataVec<C, T> {
171 TrackedDataVec(self.data.replace(StdTracks::default()).track)
172 }
173
174 fn track(&self, data: TrackData<C, T>) {
175 match &data {
176 TrackData::Enter(func, _) => {
177 self.push_func(*func);
178 self.append_track(data);
179 }
180 TrackData::Exit() => {
181 self.append_track(data);
182 self.pop_func();
183 }
184 TrackData::Ok(_, _)
185 | TrackData::Err(_, _, _)
186 | TrackData::Warn(_, _)
187 | TrackData::Info(_, _)
188 | TrackData::Debug(_, _) => {
189 self.append_track(data);
190 }
191 }
192 }
193}
194
195impl<C, T> Default for StdTracker<C, T>
196where
197 T: AsBytes + Clone,
198 C: Code,
199{
200 fn default() -> Self {
201 Self::new()
202 }
203}
204
205impl<C, T> Default for StdTracks<C, T>
206where
207 T: AsBytes + Clone,
208 C: Code,
209{
210 fn default() -> Self {
211 Self {
212 func: Default::default(),
213 track: Default::default(),
214 }
215 }
216}