1use crate::deserialize::*;
2use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema};
4use std::{borrow::Cow, str::FromStr};
5use struct_patch::Patch;
6
7#[cfg(feature = "permissive")]
8impl<T> JsonSchema for ParsableStruct<T>
9where
10 T: Clone + JsonSchema + FromStr,
11{
12 fn schema_id() -> Cow<'static, str> {
13 format!("ParsableStruct<{}>", T::schema_name()).into()
14 }
15
16 fn schema_name() -> Cow<'static, str> {
17 format!("ParsableStruct_{}", T::schema_name()).into()
18 }
19
20 fn json_schema(generator: &mut SchemaGenerator) -> Schema {
21 json_schema!({
22 "title": Self::schema_id(),
23 "oneOf": [
24 generator.subschema_for::<T>(),
25 generator.subschema_for::<String>(),
26 ]
27 })
28 }
29}
30
31#[cfg(feature = "permissive")]
32impl<T> JsonSchema for OneOrMany<T>
33where
34 T: Clone + JsonSchema,
35{
36 fn schema_id() -> Cow<'static, str> {
37 format!("OneOrMany<{}>", T::schema_name()).into()
38 }
39 fn schema_name() -> Cow<'static, str> {
40 format!("OneOrMany_{}", T::schema_name()).into()
41 }
42
43 fn json_schema(generator: &mut SchemaGenerator) -> Schema {
44 json_schema!({
45 "title": Self::schema_id(),
46 "oneOf": [
47 generator.subschema_for::<T>(),
48 {
49 "type": "array",
50 "items": generator.subschema_for::<T>()
51 }
52 ]
53 })
54 }
55}
56
57impl<T> JsonSchema for VecPatch<T>
58where
59 T: Clone + JsonSchema,
60{
61 fn schema_id() -> Cow<'static, str> {
62 format!("VecPatch<{}>", T::schema_name()).into()
63 }
64 fn schema_name() -> Cow<'static, str> {
65 format!("VecPatch_{}", T::schema_name()).into()
66 }
67
68 fn json_schema(generator: &mut SchemaGenerator) -> Schema {
69 let type_schema = generator.subschema_for::<T>();
70 let array_schema = json_schema!({
71 "type": "array",
72 "items": type_schema
73 });
74 let patterns_schema = json_schema!({
75 "type": "object",
76 "patternProperties": {
77 r"_": array_schema,
79 r"^\d+$": type_schema,
81 r"^\+\d+$": array_schema,
83 r"^\d+\+$": array_schema,
85 r"^\+$": array_schema,
87 }
88 });
89
90 let one_of = vec![
91 #[cfg(feature = "permissive")]
92 type_schema,
93 array_schema,
94 patterns_schema,
95 ];
96
97 json_schema!({
98 "title": Self::schema_id(),
99 "oneOf": one_of
100 })
101 }
102}
103
104impl<T, P> JsonSchema for VecDeepPatch<T, P>
105where
106 T: Clone + Patch<P> + From<P>,
107 P: Clone + JsonSchema,
108{
109 fn schema_id() -> Cow<'static, str> {
110 format!("VecDeepPatch<{}>", P::schema_name()).into()
111 }
112 fn schema_name() -> Cow<'static, str> {
113 format!("VecDeepPatch_{}", P::schema_name()).into()
114 }
115
116 fn json_schema(generator: &mut SchemaGenerator) -> Schema {
117 let type_schema = generator.subschema_for::<P>();
118 let array_schema = json_schema!({
119 "type": "array",
120 "items": type_schema
121 });
122 let patterns_schema = json_schema!({
123 "type": "object",
124 "patternProperties": {
125 r"_": array_schema,
127 r"^\d+$": type_schema,
129 r"^\d+<$": type_schema,
131 r"^\+\d+$": array_schema,
133 r"^\d+\+$": array_schema,
135 r"^\+$": array_schema,
137 }
138 });
139
140 let one_of = vec![
141 #[cfg(feature = "permissive")]
142 type_schema,
143 array_schema,
144 patterns_schema,
145 ];
146
147 json_schema!({
148 "title": Self::schema_id(),
149 "oneOf": one_of
150 })
151 }
152}
153
154impl<K, V> JsonSchema for HashMapPatch<K, V>
155where
156 K: Clone + Eq + std::hash::Hash + JsonSchema,
157 V: Clone + JsonSchema,
158{
159 fn schema_id() -> Cow<'static, str> {
160 format!("HashMapPatch<{}, {}>", K::schema_name(), V::schema_name()).into()
161 }
162 fn schema_name() -> Cow<'static, str> {
163 format!("HashMapPatch_{}_{}", K::schema_name(), V::schema_name()).into()
164 }
165
166 fn json_schema(generator: &mut SchemaGenerator) -> Schema {
167 json_schema!({
168 "title": Self::schema_id(),
169 "type": "object",
170 "patternProperties": {
171 "^.+$": generator.subschema_for::<Option<V>>()
172 }
173 })
174 }
175}
176
177impl<K, V> JsonSchema for HashMapDeepPatch<K, V>
178where
179 K: Clone + Eq + std::hash::Hash + JsonSchema,
180 V: Clone + JsonSchema,
181{
182 fn schema_id() -> Cow<'static, str> {
183 format!(
184 "HashMapDeepPatch<{}, {}>",
185 K::schema_name(),
186 V::schema_name()
187 )
188 .into()
189 }
190 fn schema_name() -> Cow<'static, str> {
191 format!("HashMapDeepPatch_{}_{}", K::schema_name(), V::schema_name()).into()
192 }
193
194 fn json_schema(generator: &mut SchemaGenerator) -> Schema {
195 json_schema!({
196 "title": Self::schema_id(),
197 "type": "object",
198 "patternProperties": {
199 "^.+$": generator.subschema_for::<Option<V>>()
200 }
201 })
202 }
203}
204
205pub fn optional_string_or_number_schema(_gen: &mut SchemaGenerator) -> Schema {
206 json_schema!({
207 "type": [
208 "string",
209 "number",
210 "null"
211 ],
212 "default": null,
213 "nullable": true
214 })
215}