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
86pub fn perform_visit<S: Into<PathSegment>>(
89 visitor: &mut dyn Visitor,
90 node: &dyn Visitable,
91 seg: S,
92) {
93 let seg = seg.into();
94 let should_push = !matches!(seg, PathSegment::Empty);
95 if should_push {
96 visitor.push(seg);
97 }
98 visitor.visit(node, Event::Enter);
99 node.drive(visitor);
100 visitor.visit(node, Event::Exit);
101 if should_push {
102 visitor.pop();
103 }
104}
105
106pub fn perform_visit_mut<S: Into<PathSegment>>(
108 visitor: &mut dyn VisitorMut,
109 node: &mut dyn Visitable,
110 seg: S,
111) {
112 let seg = seg.into();
113 let should_push = !matches!(seg, PathSegment::Empty);
114 if should_push {
115 visitor.push(seg);
116 }
117 visitor.visit(node, Event::Enter);
118 node.drive_mut(visitor);
119 visitor.visit(node, Event::Exit);
120 if should_push {
121 visitor.pop();
122 }
123}
124
125pub trait VisitorMut {
131 fn visit(&mut self, node: &mut dyn Visitable, event: Event);
132
133 fn push(&mut self, _: PathSegment) {}
134 fn pop(&mut self) {}
135}