use crate::PathSegment;
use crate::encoding::{Encoding, Utf8Encoding};
use crate::path::Path;
use crate::scanner::error::ScannerError;
pub trait Event: Sized {
type Encoding: Encoding;
fn visit_event<'a>(
&'a mut self,
visitor: &mut impl EventVisitor<'a>,
) -> Result<(), ScannerError>;
fn visit_string_mut(&mut self, path: &Path, visit: impl FnOnce(&mut String) -> bool);
fn get_id(&self) -> Option<&str> {
None
}
}
pub trait EventVisitor<'path> {
fn push_segment(&mut self, segment: PathSegment<'path>);
fn pop_segment(&mut self);
fn visit_string<'s>(
&'s mut self,
value: &str,
) -> Result<VisitStringResult<'s, 'path>, ScannerError>;
}
pub struct VisitStringResult<'s, 'path> {
pub might_mutate: bool,
pub path: &'s Path<'path>,
}
impl Event for String {
type Encoding = Utf8Encoding;
fn visit_event<'path>(
&'path mut self,
visitor: &mut impl EventVisitor<'path>,
) -> Result<(), ScannerError> {
visitor.visit_string(self).map(|_| {})
}
fn visit_string_mut(&mut self, _path: &Path, visit: impl FnOnce(&mut String) -> bool) {
(visit)(self);
}
}
#[cfg(test)]
pub(crate) mod test {
use crate::simple_event::SimpleEvent;
use super::*;
#[derive(Debug, PartialEq, Eq)]
enum VisitOp {
Push(PathSegment<'static>),
Pop,
Visit(String),
}
struct Visitor {
path: Path<'static>,
ops: Vec<VisitOp>,
}
impl<'path> EventVisitor<'path> for Visitor {
fn push_segment(&mut self, segment: PathSegment<'path>) {
self.ops.push(VisitOp::Push(segment.into_static()));
}
fn pop_segment(&mut self) {
self.ops.push(VisitOp::Pop);
}
fn visit_string<'s>(
&'s mut self,
value: &str,
) -> Result<VisitStringResult<'s, 'path>, ScannerError> {
self.ops.push(VisitOp::Visit(value.to_string()));
Ok(VisitStringResult {
might_mutate: true,
path: &self.path,
})
}
}
#[test]
pub fn test_string_event() {
let value = "sdsisthebest";
let mut visitor = Visitor {
ops: vec![],
path: Path::root(),
};
value.to_string().visit_event(&mut visitor).unwrap();
assert_eq!(visitor.ops, vec![VisitOp::Visit(value.into()),]);
}
#[test]
pub fn test_simple_event() {
let mut event = SimpleEvent::Map(
[
(
"key-a".to_string(),
SimpleEvent::String("value-a".to_string()),
),
(
"key-b".to_string(),
SimpleEvent::Map(
[(
"key-b-1".to_string(),
SimpleEvent::String("value-b-1".to_string()),
)]
.into(),
),
),
]
.into(),
);
let mut visitor = Visitor {
ops: vec![],
path: Path::root(),
};
event.visit_event(&mut visitor).unwrap();
assert_eq!(
visitor.ops,
vec![
VisitOp::Push(PathSegment::Field("key-a".into())),
VisitOp::Visit("value-a".into()),
VisitOp::Pop,
VisitOp::Push(PathSegment::Field("key-b".into())),
VisitOp::Push(PathSegment::Field("key-b-1".into())),
VisitOp::Visit("value-b-1".into()),
VisitOp::Pop,
VisitOp::Pop,
]
);
}
}