1use crate::PathSegment;
2use crate::encoding::{Encoding, Utf8Encoding};
3use crate::path::Path;
4use crate::scanner::error::ScannerError;
5
6pub trait Event: Sized {
10 type Encoding: Encoding;
12
13 fn visit_event<'a>(
15 &'a mut self,
16 visitor: &mut impl EventVisitor<'a>,
17 ) -> Result<(), ScannerError>;
18
19 fn visit_string_mut(&mut self, path: &Path, visit: impl FnMut(&mut String) -> bool);
23
24 fn get_id(&self) -> Option<&str> {
25 None
26 }
27}
28
29pub trait EventVisitor<'path> {
30 fn push_segment(&mut self, segment: PathSegment<'path>);
31 fn pop_segment(&mut self);
32 fn visit_string<'s>(
33 &'s mut self,
34 value: &str,
35 ) -> Result<VisitStringResult<'s, 'path>, ScannerError>;
36}
37
38pub struct VisitStringResult<'s, 'path> {
39 pub might_mutate: bool,
42 pub path: &'s Path<'path>,
43}
44
45impl Event for String {
46 type Encoding = Utf8Encoding;
47
48 fn visit_event<'path>(
49 &'path mut self,
50 visitor: &mut impl EventVisitor<'path>,
51 ) -> Result<(), ScannerError> {
52 visitor.visit_string(self).map(|_| {})
53 }
54
55 fn visit_string_mut(&mut self, _path: &Path, mut visit: impl FnMut(&mut String) -> bool) {
56 (visit)(self);
57 }
58}
59
60#[cfg(test)]
61pub(crate) mod test {
62 use crate::simple_event::SimpleEvent;
63
64 use super::*;
65
66 #[derive(Debug, PartialEq, Eq)]
67 enum VisitOp {
68 Push(PathSegment<'static>),
69 Pop,
70 Visit(String),
71 }
72
73 struct Visitor {
74 path: Path<'static>,
75 ops: Vec<VisitOp>,
76 }
77
78 impl<'path> EventVisitor<'path> for Visitor {
79 fn push_segment(&mut self, segment: PathSegment<'path>) {
80 self.ops.push(VisitOp::Push(segment.into_static()));
81 }
82
83 fn pop_segment(&mut self) {
84 self.ops.push(VisitOp::Pop);
85 }
86
87 fn visit_string<'s>(
88 &'s mut self,
89 value: &str,
90 ) -> Result<VisitStringResult<'s, 'path>, ScannerError> {
91 self.ops.push(VisitOp::Visit(value.to_string()));
92 Ok(VisitStringResult {
93 might_mutate: true,
94 path: &self.path,
95 })
96 }
97 }
98
99 #[test]
100 pub fn test_string_event() {
101 let value = "sdsisthebest";
102 let mut visitor = Visitor {
103 ops: vec![],
104 path: Path::root(),
105 };
106 value.to_string().visit_event(&mut visitor).unwrap();
107 assert_eq!(visitor.ops, vec![VisitOp::Visit(value.into()),]);
108 }
109
110 #[test]
111 pub fn test_simple_event() {
112 let mut event = SimpleEvent::Map(
113 [
114 (
115 "key-a".to_string(),
116 SimpleEvent::String("value-a".to_string()),
117 ),
118 (
119 "key-b".to_string(),
120 SimpleEvent::Map(
121 [(
122 "key-b-1".to_string(),
123 SimpleEvent::String("value-b-1".to_string()),
124 )]
125 .into(),
126 ),
127 ),
128 ]
129 .into(),
130 );
131
132 let mut visitor = Visitor {
133 ops: vec![],
134 path: Path::root(),
135 };
136 event.visit_event(&mut visitor).unwrap();
137
138 assert_eq!(
139 visitor.ops,
140 vec![
141 VisitOp::Push(PathSegment::Field("key-a".into())),
142 VisitOp::Visit("value-a".into()),
143 VisitOp::Pop,
144 VisitOp::Push(PathSegment::Field("key-b".into())),
145 VisitOp::Push(PathSegment::Field("key-b-1".into())),
146 VisitOp::Visit("value-b-1".into()),
147 VisitOp::Pop,
148 VisitOp::Pop,
149 ]
150 );
151 }
152}