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::new(msg));
15 }
16
17 pub fn issue_at(&mut self, seg: PathSegment, msg: impl Into<String>) {
18 self.add_issue_at(seg, Issue::new(msg));
19 }
20}
21
22pub struct ScopedContext<'a> {
24 ctx: &'a mut dyn VisitorContext,
25 seg: PathSegment,
26}
27
28impl<'a> ScopedContext<'a> {
29 #[must_use]
30 pub fn new(ctx: &'a mut dyn VisitorContext, seg: PathSegment) -> Self {
31 Self { ctx, seg }
32 }
33}
34
35impl VisitorContext for ScopedContext<'_> {
36 fn add_issue(&mut self, issue: Issue) {
37 self.ctx.add_issue_at(self.seg.clone(), issue);
38 }
39
40 fn add_issue_at(&mut self, _seg: PathSegment, issue: Issue) {
41 self.ctx.add_issue_at(self.seg.clone(), issue);
42 }
43}
44
45#[derive(Clone, Debug, Default)]
50pub struct Issue {
51 message: String,
52}
53
54impl Issue {
55 #[must_use]
56 pub fn new(message: impl Into<String>) -> Self {
57 Self {
58 message: message.into(),
59 }
60 }
61
62 #[must_use]
63 pub fn message(&self) -> &str {
64 &self.message
65 }
66
67 #[must_use]
68 pub fn into_message(self) -> String {
69 self.message
70 }
71}
72
73#[derive(Clone, Debug)]
78pub enum PathSegment {
79 Empty,
80 Field(&'static str),
81 Index(usize),
82}
83
84impl From<&'static str> for PathSegment {
85 fn from(s: &'static str) -> Self {
86 Self::Field(s)
87 }
88}
89
90impl From<usize> for PathSegment {
91 fn from(i: usize) -> Self {
92 Self::Index(i)
93 }
94}
95
96impl From<Option<&'static str>> for PathSegment {
97 fn from(opt: Option<&'static str>) -> Self {
98 match opt {
99 Some(s) if !s.is_empty() => Self::Field(s),
100 _ => Self::Empty,
101 }
102 }
103}