schemars/
ser.rs

1use crate::_alloc_prelude::*;
2use crate::_private::allow_null;
3use crate::{json_schema, Schema, SchemaGenerator};
4use core::fmt::Display;
5use serde_json::{Error, Map, Value};
6
7pub(crate) struct Serializer<'a> {
8    pub(crate) generator: &'a mut SchemaGenerator,
9    pub(crate) include_title: bool,
10}
11
12pub(crate) struct SerializeSeq<'a> {
13    generator: &'a mut SchemaGenerator,
14    items: Vec<Schema>,
15}
16
17pub(crate) struct SerializeTuple<'a> {
18    generator: &'a mut SchemaGenerator,
19    items: Vec<Schema>,
20    title: &'static str,
21}
22
23pub(crate) struct SerializeMap<'a> {
24    generator: &'a mut SchemaGenerator,
25    properties: Map<String, Value>,
26    current_key: Option<String>,
27    title: &'static str,
28}
29
30macro_rules! forward_to_subschema_for {
31    ($fn:ident, $ty:ty) => {
32        fn $fn(self, _value: $ty) -> Result<Self::Ok, Self::Error> {
33            Ok(self.generator.subschema_for::<$ty>())
34        }
35    };
36}
37
38macro_rules! return_instance_type {
39    ($fn:ident, $ty:ty, $instance_type:expr) => {
40        fn $fn(self, _value: $ty) -> Result<Self::Ok, Self::Error> {
41            Ok(json_schema!({
42                "type": $instance_type
43            }))
44        }
45    };
46}
47
48impl<'a> serde::Serializer for Serializer<'a> {
49    type Ok = Schema;
50    type Error = Error;
51
52    type SerializeSeq = SerializeSeq<'a>;
53    type SerializeTuple = SerializeTuple<'a>;
54    type SerializeTupleStruct = SerializeTuple<'a>;
55    type SerializeTupleVariant = Self;
56    type SerializeMap = SerializeMap<'a>;
57    type SerializeStruct = SerializeMap<'a>;
58    type SerializeStructVariant = Self;
59
60    return_instance_type!(serialize_i8, i8, "integer");
61    return_instance_type!(serialize_i16, i16, "integer");
62    return_instance_type!(serialize_i32, i32, "integer");
63    return_instance_type!(serialize_i64, i64, "integer");
64    return_instance_type!(serialize_i128, i128, "integer");
65    return_instance_type!(serialize_u8, u8, "integer");
66    return_instance_type!(serialize_u16, u16, "integer");
67    return_instance_type!(serialize_u32, u32, "integer");
68    return_instance_type!(serialize_u64, u64, "integer");
69    return_instance_type!(serialize_u128, u128, "integer");
70    return_instance_type!(serialize_f32, f32, "number");
71    return_instance_type!(serialize_f64, f64, "number");
72
73    forward_to_subschema_for!(serialize_bool, bool);
74    forward_to_subschema_for!(serialize_char, char);
75    forward_to_subschema_for!(serialize_str, &str);
76    forward_to_subschema_for!(serialize_bytes, &[u8]);
77
78    fn collect_str<T>(self, _value: &T) -> Result<Self::Ok, Self::Error>
79    where
80        T: Display + ?Sized,
81    {
82        Ok(self.generator.subschema_for::<&str>())
83    }
84
85    fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
86    where
87        K: serde::Serialize,
88        V: serde::Serialize,
89        I: IntoIterator<Item = (K, V)>,
90    {
91        let value_schema = iter
92            .into_iter()
93            .try_fold(None, |acc, (_, v)| {
94                if acc == Some(true.into()) {
95                    return Ok(acc);
96                }
97
98                let schema = v.serialize(Serializer {
99                    generator: self.generator,
100                    include_title: false,
101                })?;
102                Ok(match &acc {
103                    None => Some(schema),
104                    Some(items) if items != &schema => Some(true.into()),
105                    _ => acc,
106                })
107            })?
108            .unwrap_or(true.into());
109
110        Ok(json_schema!({
111            "type": "object",
112            "additionalProperties": value_schema,
113        }))
114    }
115
116    fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
117        Ok(self.generator.subschema_for::<Value>())
118    }
119
120    fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
121        self.serialize_none()
122    }
123
124    fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
125    where
126        T: serde::Serialize + ?Sized,
127    {
128        let mut schema = value.serialize(Serializer {
129            generator: self.generator,
130            include_title: false,
131        })?;
132
133        allow_null(self.generator, &mut schema);
134
135        Ok(schema)
136    }
137
138    fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
139        Ok(self.generator.subschema_for::<()>())
140    }
141
142    fn serialize_unit_variant(
143        self,
144        _name: &'static str,
145        _variant_index: u32,
146        _variant: &'static str,
147    ) -> Result<Self::Ok, Self::Error> {
148        Ok(true.into())
149    }
150
151    fn serialize_newtype_struct<T>(
152        self,
153        name: &'static str,
154        value: &T,
155    ) -> Result<Self::Ok, Self::Error>
156    where
157        T: serde::Serialize + ?Sized,
158    {
159        let include_title = self.include_title;
160        let mut schema = value.serialize(self)?;
161
162        if include_title && !name.is_empty() {
163            schema.insert("title".into(), name.into());
164        }
165
166        Ok(schema)
167    }
168
169    fn serialize_newtype_variant<T>(
170        self,
171        _name: &'static str,
172        _variant_index: u32,
173        _variant: &'static str,
174        _value: &T,
175    ) -> Result<Self::Ok, Self::Error>
176    where
177        T: serde::Serialize + ?Sized,
178    {
179        Ok(true.into())
180    }
181
182    fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
183        Ok(SerializeSeq {
184            generator: self.generator,
185            items: Vec::new(),
186        })
187    }
188
189    fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
190        Ok(SerializeTuple {
191            generator: self.generator,
192            items: Vec::with_capacity(len),
193            title: "",
194        })
195    }
196
197    fn serialize_tuple_struct(
198        self,
199        name: &'static str,
200        len: usize,
201    ) -> Result<Self::SerializeTupleStruct, Self::Error> {
202        let title = if self.include_title { name } else { "" };
203        Ok(SerializeTuple {
204            generator: self.generator,
205            items: Vec::with_capacity(len),
206            title,
207        })
208    }
209
210    fn serialize_tuple_variant(
211        self,
212        _name: &'static str,
213        _variant_index: u32,
214        _variant: &'static str,
215        _len: usize,
216    ) -> Result<Self::SerializeTupleVariant, Self::Error> {
217        Ok(self)
218    }
219
220    fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
221        Ok(SerializeMap {
222            generator: self.generator,
223            properties: Map::new(),
224            current_key: None,
225            title: "",
226        })
227    }
228
229    fn serialize_struct(
230        self,
231        name: &'static str,
232        _len: usize,
233    ) -> Result<Self::SerializeStruct, Self::Error> {
234        let title = if self.include_title { name } else { "" };
235        Ok(SerializeMap {
236            generator: self.generator,
237            properties: Map::new(),
238            current_key: None,
239            title,
240        })
241    }
242
243    fn serialize_struct_variant(
244        self,
245        _name: &'static str,
246        _variant_index: u32,
247        _variant: &'static str,
248        _len: usize,
249    ) -> Result<Self::SerializeStructVariant, Self::Error> {
250        Ok(self)
251    }
252}
253
254impl serde::ser::SerializeTupleVariant for Serializer<'_> {
255    type Ok = Schema;
256    type Error = Error;
257
258    fn serialize_field<T>(&mut self, _value: &T) -> Result<(), Self::Error>
259    where
260        T: serde::Serialize + ?Sized,
261    {
262        Ok(())
263    }
264
265    fn end(self) -> Result<Self::Ok, Self::Error> {
266        Ok(true.into())
267    }
268}
269
270impl serde::ser::SerializeStructVariant for Serializer<'_> {
271    type Ok = Schema;
272    type Error = Error;
273
274    fn serialize_field<T>(&mut self, _key: &'static str, _value: &T) -> Result<(), Self::Error>
275    where
276        T: serde::Serialize + ?Sized,
277    {
278        Ok(())
279    }
280
281    fn end(self) -> Result<Self::Ok, Self::Error> {
282        Ok(true.into())
283    }
284}
285
286impl serde::ser::SerializeSeq for SerializeSeq<'_> {
287    type Ok = Schema;
288    type Error = Error;
289
290    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
291    where
292        T: serde::Serialize + ?Sized,
293    {
294        if self.items.first() == Some(&true.into()) {
295            // Schema already allows any value, so no point in extending it
296            return Ok(());
297        }
298
299        let schema = value.serialize(Serializer {
300            generator: self.generator,
301            include_title: false,
302        })?;
303
304        if schema == true {
305            self.items = vec![schema];
306        } else if !self.items.contains(&schema) {
307            self.items.push(schema);
308        }
309
310        Ok(())
311    }
312
313    fn end(mut self) -> Result<Self::Ok, Self::Error> {
314        let items = match self.items.len() {
315            0 => true.into(),
316            1 => self.items.remove(0),
317            _ => json_schema!({
318                "anyOf": self.items
319            }),
320        };
321
322        Ok(json_schema!({
323            "type": "array",
324            "items": items
325        }))
326    }
327}
328
329impl serde::ser::SerializeTuple for SerializeTuple<'_> {
330    type Ok = Schema;
331    type Error = Error;
332
333    fn serialize_element<T>(&mut self, value: &T) -> Result<(), Self::Error>
334    where
335        T: serde::Serialize + ?Sized,
336    {
337        let schema = value.serialize(Serializer {
338            generator: self.generator,
339            include_title: false,
340        })?;
341        self.items.push(schema);
342        Ok(())
343    }
344
345    fn end(self) -> Result<Self::Ok, Self::Error> {
346        let len = self.items.len();
347        let mut schema = json_schema!({
348            "type": "array",
349            "prefixItems": self.items,
350            "maxItems": len,
351            "minItems": len,
352        });
353
354        if !self.title.is_empty() {
355            schema
356                .ensure_object()
357                .insert("title".into(), self.title.into());
358        }
359
360        Ok(schema)
361    }
362}
363
364impl serde::ser::SerializeTupleStruct for SerializeTuple<'_> {
365    type Ok = Schema;
366    type Error = Error;
367
368    fn serialize_field<T>(&mut self, value: &T) -> Result<(), Self::Error>
369    where
370        T: serde::Serialize + ?Sized,
371    {
372        serde::ser::SerializeTuple::serialize_element(self, value)
373    }
374
375    fn end(self) -> Result<Self::Ok, Self::Error> {
376        serde::ser::SerializeTuple::end(self)
377    }
378}
379
380impl serde::ser::SerializeMap for SerializeMap<'_> {
381    type Ok = Schema;
382    type Error = Error;
383
384    fn serialize_key<T>(&mut self, key: &T) -> Result<(), Self::Error>
385    where
386        T: serde::Serialize + ?Sized,
387    {
388        // FIXME this is too lenient - we should return an error if serde_json
389        // doesn't allow T to be a key of a map.
390        let json = serde_json::to_string(key)?;
391        self.current_key = Some(
392            json.trim_start_matches('"')
393                .trim_end_matches('"')
394                .to_string(),
395        );
396
397        Ok(())
398    }
399
400    fn serialize_value<T>(&mut self, value: &T) -> Result<(), Self::Error>
401    where
402        T: serde::Serialize + ?Sized,
403    {
404        let key = self.current_key.take().unwrap_or_default();
405        let schema = value.serialize(Serializer {
406            generator: self.generator,
407            include_title: false,
408        })?;
409        self.properties.insert(key, schema.into());
410
411        Ok(())
412    }
413
414    fn end(self) -> Result<Self::Ok, Self::Error> {
415        let mut schema = json_schema!({
416            "type": "object",
417            "properties": self.properties,
418        });
419
420        if !self.title.is_empty() {
421            schema
422                .ensure_object()
423                .insert("title".into(), self.title.into());
424        }
425
426        Ok(schema)
427    }
428}
429
430impl serde::ser::SerializeStruct for SerializeMap<'_> {
431    type Ok = Schema;
432    type Error = Error;
433
434    fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
435    where
436        T: serde::Serialize + ?Sized,
437    {
438        let prop_schema = value.serialize(Serializer {
439            generator: self.generator,
440            include_title: false,
441        })?;
442        self.properties.insert(key.to_string(), prop_schema.into());
443
444        Ok(())
445    }
446
447    fn end(self) -> Result<Self::Ok, Self::Error> {
448        serde::ser::SerializeMap::end(self)
449    }
450}