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