icydb_core/visitor/
context.rs1pub trait VisitorContext {
8 fn add_issue(&mut self, issue: Issue);
9 fn add_issue_at(&mut self, seg: PathSegment, issue: Issue);
10}
11
12impl dyn VisitorContext + '_ {
13 pub fn issue(&mut self, msg: impl Into<String>) {
14 self.add_issue(Issue {
15 message: msg.into(),
16 });
17 }
18
19 pub fn issue_at(&mut self, seg: PathSegment, msg: impl Into<String>) {
20 self.add_issue_at(
21 seg,
22 Issue {
23 message: msg.into(),
24 },
25 );
26 }
27}
28
29pub struct ScopedContext<'a> {
31 ctx: &'a mut dyn VisitorContext,
32 seg: PathSegment,
33}
34
35impl<'a> ScopedContext<'a> {
36 #[must_use]
37 pub fn new(ctx: &'a mut dyn VisitorContext, seg: PathSegment) -> Self {
38 Self { ctx, seg }
39 }
40}
41
42impl VisitorContext for ScopedContext<'_> {
43 fn add_issue(&mut self, issue: Issue) {
44 self.ctx.add_issue_at(self.seg.clone(), issue);
45 }
46
47 fn add_issue_at(&mut self, _seg: PathSegment, issue: Issue) {
48 self.ctx.add_issue_at(self.seg.clone(), issue);
49 }
50}
51
52#[derive(Clone, Debug, Default)]
57pub struct Issue {
58 pub message: String,
59}
60
61#[derive(Clone, Debug)]
66pub enum PathSegment {
67 Empty,
68 Field(&'static str),
69 Index(usize),
70}
71
72impl From<&'static str> for PathSegment {
73 fn from(s: &'static str) -> Self {
74 Self::Field(s)
75 }
76}
77
78impl From<usize> for PathSegment {
79 fn from(i: usize) -> Self {
80 Self::Index(i)
81 }
82}
83
84impl From<Option<&'static str>> for PathSegment {
85 fn from(opt: Option<&'static str>) -> Self {
86 match opt {
87 Some(s) if !s.is_empty() => Self::Field(s),
88 _ => Self::Empty,
89 }
90 }
91}