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}