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 #[serde(rename_all = "camelCase")]
34 pub struct Xml {
35 /// Used to replace the name of attribute or type used in schema property.
36 /// When used with [`Xml::wrapped`] attribute the name will be used as a wrapper name
37 /// for wrapped array instead of the item or type name.
38 #[serde(skip_serializing_if = "Option::is_none")]
39 pub name: Option<Cow<'static, str>>,
40
41 /// Valid uri definition of namespace used in xml.
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub namespace: Option<Cow<'static, str>>,
44
45 /// Prefix for xml element [`Xml::name`].
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub prefix: Option<Cow<'static, str>>,
48
49 /// XML node type for this schema.
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub node_type: Option<Cow<'static, str>>,
52
53 /// Flag deciding will this attribute translate to element attribute instead of xml element.
54 #[serde(skip_serializing_if = "Option::is_none")]
55 pub attribute: Option<bool>,
56
57 /// Flag only usable with array definition. If set to true the output xml will wrap the array of items
58 /// `<pets><pet></pet></pets>` instead of unwrapped `<pet></pet>`.
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub wrapped: Option<bool>,
61 }
62}
63
64impl Xml {
65 /// Construct a new [`Xml`] object.
66 pub fn new() -> Self {
67 Self {
68 ..Default::default()
69 }
70 }
71}
72
73impl XmlBuilder {
74 /// Add [`Xml::name`] to xml object.
75 ///
76 /// Builder style chainable consuming add name method.
77 pub fn name<S: Into<Cow<'static, str>>>(mut self, name: Option<S>) -> Self {
78 set_value!(self name name.map(|name| name.into()))
79 }
80
81 /// Add [`Xml::namespace`] to xml object.
82 ///
83 /// Builder style chainable consuming add namespace method.
84 pub fn namespace<S: Into<Cow<'static, str>>>(mut self, namespace: Option<S>) -> Self {
85 set_value!(self namespace namespace.map(|namespace| namespace.into()))
86 }
87
88 /// Add [`Xml::prefix`] to xml object.
89 ///
90 /// Builder style chainable consuming add prefix method.
91 pub fn prefix<S: Into<Cow<'static, str>>>(mut self, prefix: Option<S>) -> Self {
92 set_value!(self prefix prefix.map(|prefix| prefix.into()))
93 }
94
95 /// Add [`Xml::node_type`] to xml object.
96 ///
97 /// Builder style chainable consuming add node type method.
98 pub fn node_type<S: Into<Cow<'static, str>>>(mut self, node_type: Option<S>) -> Self {
99 set_value!(self node_type node_type.map(|node_type| node_type.into()))
100 }
101
102 /// Mark [`Xml`] object as attribute. See [`Xml::attribute`].
103 ///
104 /// Builder style chainable consuming add attribute method.
105 pub fn attribute(mut self, attribute: Option<bool>) -> Self {
106 set_value!(self attribute attribute)
107 }
108
109 /// Mark [`Xml`] object wrapped. See [`Xml::wrapped`].
110 ///
111 /// Builder style chainable consuming add wrapped method.
112 pub fn wrapped(mut self, wrapped: Option<bool>) -> Self {
113 set_value!(self wrapped wrapped)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::Xml;
120
121 #[test]
122 fn xml_new() {
123 let xml = Xml::new();
124
125 assert!(xml.name.is_none());
126 assert!(xml.namespace.is_none());
127 assert!(xml.prefix.is_none());
128 assert!(xml.attribute.is_none());
129 assert!(xml.wrapped.is_none());
130 }
131}