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 pub fn new() -> Self {
46 Self {
47 ..Default::default()
48 }
49 }
50}
51
52impl Xml {
53 /// Add [`Xml::name`] to xml object.
54 ///
55 /// Builder style chainable consuming add name method.
56 pub fn name<S: Into<Cow<'static, str>>>(mut self, name: S) -> Self {
57 self.name = Some(name.into());
58 self
59 }
60
61 /// Add [`Xml::namespace`] to xml object.
62 ///
63 /// Builder style chainable consuming add namespace method.
64 pub fn namespace<S: Into<Cow<'static, str>>>(mut self, namespace: S) -> Self {
65 self.namespace = Some(namespace.into());
66 self
67 }
68
69 /// Add [`Xml::prefix`] to xml object.
70 ///
71 /// Builder style chainable consuming add prefix method.
72 pub fn prefix<S: Into<Cow<'static, str>>>(mut self, prefix: S) -> Self {
73 self.prefix = Some(prefix.into());
74 self
75 }
76
77 /// Mark [`Xml`] object as attribute. See [`Xml::attribute`]
78 ///
79 /// Builder style chainable consuming add attribute method.
80 pub fn attribute(mut self, attribute: bool) -> Self {
81 self.attribute = Some(attribute);
82 self
83 }
84
85 /// Mark [`Xml`] object wrapped. See [`Xml::wrapped`]
86 ///
87 /// Builder style chainable consuming add wrapped method.
88 pub fn wrapped(mut self, wrapped: bool) -> Self {
89 self.wrapped = Some(wrapped);
90 self
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::Xml;
97
98 #[test]
99 fn xml_new() {
100 let mut xml = Xml::new();
101
102 assert!(xml.name.is_none());
103 assert!(xml.namespace.is_none());
104 assert!(xml.prefix.is_none());
105 assert!(xml.attribute.is_none());
106 assert!(xml.wrapped.is_none());
107
108 xml = xml.name("name");
109 assert!(xml.name.is_some());
110
111 xml = xml.namespace("namespave");
112 assert!(xml.namespace.is_some());
113
114 xml = xml.prefix("prefix");
115 assert!(xml.prefix.is_some());
116
117 xml = xml.attribute(true);
118 assert!(xml.attribute.is_some());
119
120 xml = xml.wrapped(true);
121 assert!(xml.wrapped.is_some());
122 }
123}