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