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