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