icydb_core/visitor/
context.rs1use crate::sanitize::SanitizeWriteContext;
7
8pub trait VisitorContext {
16 fn add_issue(&mut self, issue: Issue);
17 fn add_issue_at(&mut self, seg: PathSegment, issue: Issue);
18
19 fn sanitize_write_context(&self) -> Option<SanitizeWriteContext> {
20 None
21 }
22}
23
24impl dyn VisitorContext + '_ {
25 pub fn issue(&mut self, msg: impl Into<String>) {
26 self.add_issue(Issue::new(msg));
27 }
28
29 pub fn issue_at(&mut self, seg: PathSegment, msg: impl Into<String>) {
30 self.add_issue_at(seg, Issue::new(msg));
31 }
32}
33
34pub struct ScopedContext<'a> {
36 ctx: &'a mut dyn VisitorContext,
37 seg: PathSegment,
38}
39
40impl<'a> ScopedContext<'a> {
41 #[must_use]
42 pub fn new(ctx: &'a mut dyn VisitorContext, seg: PathSegment) -> Self {
43 Self { ctx, seg }
44 }
45}
46
47impl VisitorContext for ScopedContext<'_> {
48 fn add_issue(&mut self, issue: Issue) {
49 self.ctx.add_issue_at(self.seg.clone(), issue);
50 }
51
52 fn add_issue_at(&mut self, _seg: PathSegment, issue: Issue) {
53 self.ctx.add_issue_at(self.seg.clone(), issue);
54 }
55
56 fn sanitize_write_context(&self) -> Option<SanitizeWriteContext> {
57 self.ctx.sanitize_write_context()
58 }
59}
60
61#[derive(Clone, Debug, Default)]
66pub struct Issue {
67 message: String,
68}
69
70impl Issue {
71 #[must_use]
72 pub fn new(message: impl Into<String>) -> Self {
73 Self {
74 message: message.into(),
75 }
76 }
77
78 #[must_use]
79 pub fn message(&self) -> &str {
80 &self.message
81 }
82
83 #[must_use]
84 pub fn into_message(self) -> String {
85 self.message
86 }
87}
88
89#[derive(Clone, Debug)]
94pub enum PathSegment {
95 Empty,
96 Field(&'static str),
97 Index(usize),
98}
99
100impl From<&'static str> for PathSegment {
101 fn from(s: &'static str) -> Self {
102 Self::Field(s)
103 }
104}
105
106impl From<usize> for PathSegment {
107 fn from(i: usize) -> Self {
108 Self::Index(i)
109 }
110}
111
112impl From<Option<&'static str>> for PathSegment {
113 fn from(opt: Option<&'static str>) -> Self {
114 match opt {
115 Some(s) if !s.is_empty() => Self::Field(s),
116 _ => Self::Empty,
117 }
118 }
119}