apistos_schemars/
visit.rs1use crate::schema::{RootSchema, Schema, SchemaObject, SingleOrVec};
30
31pub trait Visitor {
33 fn visit_root_schema(&mut self, root: &mut RootSchema) {
37 visit_root_schema(self, root)
38 }
39
40 fn visit_schema(&mut self, schema: &mut Schema) {
44 visit_schema(self, schema)
45 }
46
47 fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
51 visit_schema_object(self, schema)
52 }
53}
54
55pub fn visit_root_schema<V: Visitor + ?Sized>(v: &mut V, root: &mut RootSchema) {
57 v.visit_schema_object(&mut root.schema);
58 visit_map_values(v, &mut root.definitions);
59}
60
61pub fn visit_schema<V: Visitor + ?Sized>(v: &mut V, schema: &mut Schema) {
63 if let Schema::Object(schema) = schema {
64 v.visit_schema_object(schema)
65 }
66}
67
68pub fn visit_schema_object<V: Visitor + ?Sized>(v: &mut V, schema: &mut SchemaObject) {
70 if let Some(sub) = &mut schema.subschemas {
71 visit_vec(v, &mut sub.all_of);
72 visit_vec(v, &mut sub.any_of);
73 visit_vec(v, &mut sub.one_of);
74 visit_box(v, &mut sub.not);
75 visit_box(v, &mut sub.if_schema);
76 visit_box(v, &mut sub.then_schema);
77 visit_box(v, &mut sub.else_schema);
78 }
79
80 if let Some(arr) = &mut schema.array {
81 visit_single_or_vec(v, &mut arr.items);
82 visit_box(v, &mut arr.additional_items);
83 visit_box(v, &mut arr.contains);
84 }
85
86 if let Some(obj) = &mut schema.object {
87 visit_map_values(v, &mut obj.properties);
88 visit_map_values(v, &mut obj.pattern_properties);
89 visit_box(v, &mut obj.additional_properties);
90 visit_box(v, &mut obj.property_names);
91 }
92}
93
94fn visit_box<V: Visitor + ?Sized>(v: &mut V, target: &mut Option<Box<Schema>>) {
95 if let Some(s) = target {
96 v.visit_schema(s)
97 }
98}
99
100fn visit_vec<V: Visitor + ?Sized>(v: &mut V, target: &mut Option<Vec<Schema>>) {
101 if let Some(vec) = target {
102 for s in vec {
103 v.visit_schema(s)
104 }
105 }
106}
107
108fn visit_map_values<V: Visitor + ?Sized>(v: &mut V, target: &mut crate::Map<String, Schema>) {
109 for s in target.values_mut() {
110 v.visit_schema(s)
111 }
112}
113
114fn visit_single_or_vec<V: Visitor + ?Sized>(v: &mut V, target: &mut Option<SingleOrVec<Schema>>) {
115 match target {
116 None => {}
117 Some(SingleOrVec::Single(s)) => v.visit_schema(s),
118 Some(SingleOrVec::Vec(vec)) => {
119 for s in vec {
120 v.visit_schema(s)
121 }
122 }
123 }
124}
125
126#[derive(Debug, Clone)]
130pub struct ReplaceBoolSchemas {
131 pub skip_additional_properties: bool,
133}
134
135impl Visitor for ReplaceBoolSchemas {
136 fn visit_schema(&mut self, schema: &mut Schema) {
137 visit_schema(self, schema);
138
139 if let Schema::Bool(b) = *schema {
140 *schema = Schema::Bool(b).into_object().into()
141 }
142 }
143
144 fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
145 if self.skip_additional_properties {
146 if let Some(obj) = &mut schema.object {
147 if let Some(ap) = &obj.additional_properties {
148 if let Schema::Bool(_) = ap.as_ref() {
149 let additional_properties = obj.additional_properties.take();
150 visit_schema_object(self, schema);
151 schema.object().additional_properties = additional_properties;
152
153 return;
154 }
155 }
156 }
157 }
158
159 visit_schema_object(self, schema);
160 }
161}
162
163#[derive(Debug, Clone)]
167pub struct RemoveRefSiblings;
168
169impl Visitor for RemoveRefSiblings {
170 fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
171 visit_schema_object(self, schema);
172
173 if let Some(reference) = schema.reference.take() {
174 if schema == &SchemaObject::default() {
175 schema.reference = Some(reference);
176 } else {
177 let ref_schema = Schema::new_ref(reference);
178 let all_of = &mut schema.subschemas().all_of;
179 match all_of {
180 Some(vec) => vec.push(ref_schema),
181 None => *all_of = Some(vec![ref_schema]),
182 }
183 }
184 }
185 }
186}
187
188#[derive(Debug, Clone)]
192pub struct SetSingleExample {
193 pub retain_examples: bool,
195}
196
197impl Visitor for SetSingleExample {
198 fn visit_schema_object(&mut self, schema: &mut SchemaObject) {
199 visit_schema_object(self, schema);
200
201 let first_example = schema.metadata.as_mut().and_then(|m| {
202 if self.retain_examples {
203 m.examples.first().cloned()
204 } else {
205 m.examples.drain(..).next()
206 }
207 });
208
209 if let Some(example) = first_example {
210 schema.extensions.insert("example".to_owned(), example);
211 }
212 }
213}