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) {
25 let mut visitor = SanitizeVisitor::new();
26 perform_visit_mut(&mut visitor, node, PathSegment::Empty);
27}
28
29#[derive(Clone, Copy, Debug)]
34pub enum Event {
35 Enter,
36 Exit,
37}
38
39#[derive(Debug)]
44pub enum PathSegment {
45 Empty,
46 Field(&'static str),
47 Index(usize),
48}
49
50impl From<&'static str> for PathSegment {
51 fn from(s: &'static str) -> Self {
52 Self::Field(s)
53 }
54}
55
56impl From<usize> for PathSegment {
57 fn from(i: usize) -> Self {
58 Self::Index(i)
59 }
60}
61
62impl From<Option<&'static str>> for PathSegment {
63 fn from(opt: Option<&'static str>) -> Self {
64 match opt {
65 Some(s) if !s.is_empty() => Self::Field(s),
66 _ => Self::Empty,
67 }
68 }
69}
70
71pub trait Visitor {
77 fn visit(&mut self, node: &dyn Visitable, event: Event);
79
80 fn push(&mut self, _: PathSegment) {}
82 fn pop(&mut self) {}
83}
84
85#[inline]
87pub fn perform_visit<S: Into<PathSegment>>(
88 visitor: &mut dyn Visitor,
89 node: &dyn Visitable,
90 seg: S,
91) {
92 let seg = seg.into();
93 let should_push = !matches!(seg, PathSegment::Empty);
94 if should_push {
95 visitor.push(seg);
96 }
97 visitor.visit(node, Event::Enter);
98 node.drive(visitor);
99 visitor.visit(node, Event::Exit);
100 if should_push {
101 visitor.pop();
102 }
103}
104
105#[inline]
106pub fn perform_visit_mut<S: Into<PathSegment>>(
107 visitor: &mut dyn VisitorMut,
108 node: &mut dyn Visitable,
109 seg: S,
110) {
111 let seg = seg.into();
112 let should_push = !matches!(seg, PathSegment::Empty);
113 if should_push {
114 visitor.push(seg);
115 }
116 visitor.visit(node, Event::Enter);
117 node.drive_mut(visitor);
118 visitor.visit(node, Event::Exit);
119 if should_push {
120 visitor.pop();
121 }
122}
123
124pub trait VisitorMut {
130 fn visit(&mut self, node: &mut dyn Visitable, event: Event);
131
132 fn push(&mut self, _: PathSegment) {}
133 fn pop(&mut self) {}
134}