icydb_core/visitor/
mod.rs1pub mod sanitize;
2pub mod validate;
3
4pub use sanitize::*;
5pub use validate::*;
6
7use crate::{ThisError, traits::Visitable, visitor::SanitizeVisitor};
8
9#[derive(Debug, ThisError)]
14pub enum VisitorError {
15 #[error(transparent)]
16 ValidateError(#[from] validate::ValidateError),
17}
18
19pub fn sanitize(node: &mut dyn Visitable) {
26 let mut visitor = SanitizeVisitor::new();
27 perform_visit_mut(&mut visitor, node, PathSegment::Empty);
28}
29
30#[derive(Clone, Copy, Debug)]
35pub enum Event {
36 Enter,
37 Exit,
38}
39
40#[derive(Debug)]
45pub enum PathSegment {
46 Empty,
47 Field(&'static str),
48 Index(usize),
49}
50
51impl From<&'static str> for PathSegment {
52 fn from(s: &'static str) -> Self {
53 Self::Field(s)
54 }
55}
56
57impl From<usize> for PathSegment {
58 fn from(i: usize) -> Self {
59 Self::Index(i)
60 }
61}
62
63impl From<Option<&'static str>> for PathSegment {
64 fn from(opt: Option<&'static str>) -> Self {
65 match opt {
66 Some(s) if !s.is_empty() => Self::Field(s),
67 _ => Self::Empty,
68 }
69 }
70}
71
72pub trait Visitor {
78 fn visit(&mut self, node: &dyn Visitable, event: Event);
80
81 fn push(&mut self, _: PathSegment) {}
83 fn pop(&mut self) {}
84}
85
86#[inline]
88pub fn perform_visit<S: Into<PathSegment>>(
90 visitor: &mut dyn Visitor,
91 node: &dyn Visitable,
92 seg: S,
93) {
94 let seg = seg.into();
95 let should_push = !matches!(seg, PathSegment::Empty);
96 if should_push {
97 visitor.push(seg);
98 }
99 visitor.visit(node, Event::Enter);
100 node.drive(visitor);
101 visitor.visit(node, Event::Exit);
102 if should_push {
103 visitor.pop();
104 }
105}
106
107#[inline]
108pub fn perform_visit_mut<S: Into<PathSegment>>(
110 visitor: &mut dyn VisitorMut,
111 node: &mut dyn Visitable,
112 seg: S,
113) {
114 let seg = seg.into();
115 let should_push = !matches!(seg, PathSegment::Empty);
116 if should_push {
117 visitor.push(seg);
118 }
119 visitor.visit(node, Event::Enter);
120 node.drive_mut(visitor);
121 visitor.visit(node, Event::Exit);
122 if should_push {
123 visitor.pop();
124 }
125}
126
127pub trait VisitorMut {
133 fn visit(&mut self, node: &mut dyn Visitable, event: Event);
134
135 fn push(&mut self, _: PathSegment) {}
136 fn pop(&mut self) {}
137}