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