1use crate::case_enum::all::All;
2use crate::case_enum::one::One;
3use crate::location::Located;
4use crate::{Error, NamedShapePathKey, Shape, ShapeCase};
5use indexmap::IndexMap;
6
7#[expect(unused_variables, clippy::missing_errors_doc)]
8pub trait ShapeVisitor<Output = ()> {
9 type Error: std::error::Error;
10 type Output;
11
12 fn default(&mut self, shape: &Shape) -> Result<Self::Output, Self::Error>;
13
14 fn visit_bool(
15 &mut self,
16 shape: &Shape,
17 value: &Option<bool>,
18 ) -> Result<Self::Output, Self::Error> {
19 self.default(shape)
20 }
21
22 fn visit_string(
23 &mut self,
24 shape: &Shape,
25 value: &Option<String>,
26 ) -> Result<Self::Output, Self::Error> {
27 self.default(shape)
28 }
29
30 fn visit_int(
31 &mut self,
32 shape: &Shape,
33 value: &Option<i64>,
34 ) -> Result<Self::Output, Self::Error> {
35 self.default(shape)
36 }
37
38 fn visit_float(&mut self, shape: &Shape) -> Result<Self::Output, Self::Error> {
39 self.default(shape)
40 }
41
42 fn visit_null(&mut self, shape: &Shape) -> Result<Self::Output, Self::Error> {
43 self.default(shape)
44 }
45
46 fn visit_array(
47 &mut self,
48 shape: &Shape,
49 prefix: &[Shape],
50 tail: &Shape,
51 ) -> Result<Self::Output, Self::Error> {
52 self.default(shape)
53 }
54
55 fn visit_object(
56 &mut self,
57 shape: &Shape,
58 fields: &IndexMap<String, Shape>,
59 rest: &Shape,
60 ) -> Result<Self::Output, Self::Error> {
61 self.default(shape)
62 }
63
64 fn visit_one(&mut self, shape: &Shape, one: &One) -> Result<Self::Output, Self::Error> {
65 self.default(shape)
66 }
67
68 fn visit_name(
69 &mut self,
70 shape: &Shape,
71 name: &Located<String>,
72 subpath: &[Located<NamedShapePathKey>],
73 ) -> Result<Self::Output, Self::Error> {
74 self.default(shape)
75 }
76
77 fn visit_unknown(&mut self, shape: &Shape) -> Result<Self::Output, Self::Error> {
78 self.default(shape)
79 }
80
81 fn visit_none(&mut self, shape: &Shape) -> Result<Self::Output, Self::Error> {
82 self.default(shape)
83 }
84
85 fn visit_error(&mut self, shape: &Shape, err: &Error) -> Result<Self::Output, Self::Error> {
86 self.default(shape)
87 }
88
89 fn visit_all(&mut self, shape: &Shape, all: &All) -> Result<Self::Output, Self::Error> {
90 self.default(shape)
91 }
92}
93
94impl Shape {
95 #[expect(clippy::missing_errors_doc)]
96 pub fn visit_shape<V: ShapeVisitor>(&self, visitor: &mut V) -> Result<V::Output, V::Error> {
97 match self.case.as_ref() {
98 ShapeCase::Bool(b) => visitor.visit_bool(self, b),
99 ShapeCase::String(s) => visitor.visit_string(self, s),
100 ShapeCase::Int(i) => visitor.visit_int(self, i),
101 ShapeCase::Float => visitor.visit_float(self),
102 ShapeCase::Null => visitor.visit_null(self),
103 ShapeCase::Array { prefix, tail } => visitor.visit_array(self, prefix, tail),
104 ShapeCase::Object { fields, rest } => visitor.visit_object(self, fields, rest),
105 ShapeCase::One(one) => visitor.visit_one(self, one),
106 ShapeCase::All(all) => visitor.visit_all(self, all),
107 ShapeCase::Name(name, subpath) => visitor.visit_name(self, name, subpath),
108 ShapeCase::Unknown => visitor.visit_unknown(self),
109 ShapeCase::None => visitor.visit_none(self),
110 ShapeCase::Error(err) => visitor.visit_error(self, err),
111 }
112 }
113}