utoipa/openapi/xml.rs
1//! Implements [OpenAPI Xml Object][xml_object] types.
2//!
3//! [xml_object]: https://spec.openapis.org/oas/latest.html#xml-object
4use std::borrow::Cow;
5
6use serde::{Deserialize, Serialize};
7
8use super::{builder, set_value};
9
10builder! {
11 /// # Examples
12 ///
13 /// Create [`Xml`] with [`XmlBuilder`].
14 /// ```rust
15 /// # use utoipa::openapi::xml::XmlBuilder;
16 /// let xml = XmlBuilder::new()
17 /// .name(Some("some_name"))
18 /// .prefix(Some("prefix"))
19 /// .build();
20 /// ```
21 XmlBuilder;
22 /// Implements [OpenAPI Xml Object][xml_object].
23 ///
24 /// Can be used to modify xml output format of specific [OpenAPI Schema Object][schema_object] which are
25 /// implemented in [`schema`][schema] module.
26 ///
27 /// [xml_object]: https://spec.openapis.org/oas/latest.html#xml-object
28 /// [schema_object]: https://spec.openapis.org/oas/latest.html#schema-object
29 /// [schema]: ../schema/index.html
30 #[non_exhaustive]
31 #[derive(Serialize, Deserialize, Default, Clone, PartialEq, Eq)]
32 #[cfg_attr(feature = "debug", derive(Debug))]
33 pub struct Xml {
34 /// Used to replace the name of attribute or type used in schema property.
35 /// When used with [`Xml::wrapped`] attribute the name will be used as a wrapper name
36 /// for wrapped array instead of the item or type name.
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub name: Option<Cow<'static, str>>,
39
40 /// Valid uri definition of namespace used in xml.
41 #[serde(skip_serializing_if = "Option::is_none")]
42 pub namespace: Option<Cow<'static, str>>,
43
44 /// Prefix for xml element [`Xml::name`].
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub prefix: Option<Cow<'static, str>>,
47
48 /// Flag deciding will this attribute translate to element attribute instead of xml element.
49 #[serde(skip_serializing_if = "Option::is_none")]
50 pub attribute: Option<bool>,
51
52 /// Flag only usable with array definition. If set to true the output xml will wrap the array of items
53 /// `<pets><pet></pet></pets>` instead of unwrapped `<pet></pet>`.
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub wrapped: Option<bool>,
56 }
57}
58
59impl Xml {
60 /// Construct a new [`Xml`] object.
61 pub fn new() -> Self {
62 Self {
63 ..Default::default()
64 }
65 }
66}
67
68impl XmlBuilder {
69 /// Add [`Xml::name`] to xml object.
70 ///
71 /// Builder style chainable consuming add name method.
72 pub fn name<S: Into<Cow<'static, str>>>(mut self, name: Option<S>) -> Self {
73 set_value!(self name name.map(|name| name.into()))
74 }
75
76 /// Add [`Xml::namespace`] to xml object.
77 ///
78 /// Builder style chainable consuming add namespace method.
79 pub fn namespace<S: Into<Cow<'static, str>>>(mut self, namespace: Option<S>) -> Self {
80 set_value!(self namespace namespace.map(|namespace| namespace.into()))
81 }
82
83 /// Add [`Xml::prefix`] to xml object.
84 ///
85 /// Builder style chainable consuming add prefix method.
86 pub fn prefix<S: Into<Cow<'static, str>>>(mut self, prefix: Option<S>) -> Self {
87 set_value!(self prefix prefix.map(|prefix| prefix.into()))
88 }
89
90 /// Mark [`Xml`] object as attribute. See [`Xml::attribute`]
91 ///
92 /// Builder style chainable consuming add attribute method.
93 pub fn attribute(mut self, attribute: Option<bool>) -> Self {
94 set_value!(self attribute attribute)
95 }
96
97 /// Mark [`Xml`] object wrapped. See [`Xml::wrapped`]
98 ///
99 /// Builder style chainable consuming add wrapped method.
100 pub fn wrapped(mut self, wrapped: Option<bool>) -> Self {
101 set_value!(self wrapped wrapped)
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::Xml;
108
109 #[test]
110 fn xml_new() {
111 let xml = Xml::new();
112
113 assert!(xml.name.is_none());
114 assert!(xml.namespace.is_none());
115 assert!(xml.prefix.is_none());
116 assert!(xml.attribute.is_none());
117 assert!(xml.wrapped.is_none());
118 }
119}