icydb_core/visitor/
context.rs1pub trait VisitorContext {
14 fn add_issue(&mut self, issue: Issue);
15 fn add_issue_at(&mut self, seg: PathSegment, issue: Issue);
16}
17
18impl dyn VisitorContext + '_ {
19 pub fn issue(&mut self, msg: impl Into<String>) {
20 self.add_issue(Issue::new(msg));
21 }
22
23 pub fn issue_at(&mut self, seg: PathSegment, msg: impl Into<String>) {
24 self.add_issue_at(seg, Issue::new(msg));
25 }
26}
27
28pub struct ScopedContext<'a> {
30 ctx: &'a mut dyn VisitorContext,
31 seg: PathSegment,
32}
33
34impl<'a> ScopedContext<'a> {
35 #[must_use]
36 pub fn new(ctx: &'a mut dyn VisitorContext, seg: PathSegment) -> Self {
37 Self { ctx, seg }
38 }
39}
40
41impl VisitorContext for ScopedContext<'_> {
42 fn add_issue(&mut self, issue: Issue) {
43 self.ctx.add_issue_at(self.seg.clone(), issue);
44 }
45
46 fn add_issue_at(&mut self, _seg: PathSegment, issue: Issue) {
47 self.ctx.add_issue_at(self.seg.clone(), issue);
48 }
49}
50
51#[derive(Clone, Debug, Default)]
56pub struct Issue {
57 message: String,
58}
59
60impl Issue {
61 #[must_use]
62 pub fn new(message: impl Into<String>) -> Self {
63 Self {
64 message: message.into(),
65 }
66 }
67
68 #[must_use]
69 pub fn message(&self) -> &str {
70 &self.message
71 }
72
73 #[must_use]
74 pub fn into_message(self) -> String {
75 self.message
76 }
77}
78
79#[derive(Clone, Debug)]
84pub enum PathSegment {
85 Empty,
86 Field(&'static str),
87 Index(usize),
88}
89
90impl From<&'static str> for PathSegment {
91 fn from(s: &'static str) -> Self {
92 Self::Field(s)
93 }
94}
95
96impl From<usize> for PathSegment {
97 fn from(i: usize) -> Self {
98 Self::Index(i)
99 }
100}
101
102impl From<Option<&'static str>> for PathSegment {
103 fn from(opt: Option<&'static str>) -> Self {
104 match opt {
105 Some(s) if !s.is_empty() => Self::Field(s),
106 _ => Self::Empty,
107 }
108 }
109}